From 65ad1ba320d945c9626f471c4fb0972ae49440b5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 26 May 2012 21:47:27 +0100 Subject: [PATCH 001/273] Made it possible to build the bootloader when targetting x86_64. * x86_64 is using the existing *_ia32 boot platforms. * Special flags are required when compiling the loader to get GCC to compile 32-bit code. This adds a new set of rules for compiling boot code rather than using the kernel rules, which compile using the necessary flags. * Some x86_64 private headers have been stubbed by #include'ing the x86 versions. These will be replaced later. --- Jamrules | 1 + build/jam/BootRules | 129 ++++++++++++++++++ build/jam/BuildSetup | 24 +++- configure | 11 ++ headers/private/kernel/arch/x86/apm.h | 2 +- headers/private/kernel/arch/x86_64/arch_cpu.h | 6 + headers/private/kernel/arch/x86_64/arch_int.h | 6 + .../private/kernel/arch/x86_64/arch_kernel.h | 6 + .../kernel/arch/x86_64/arch_kernel_args.h | 6 + .../kernel/arch/x86_64/arch_system_info.h | 6 + .../private/kernel/arch/x86_64/arch_thread.h | 6 + .../kernel/arch/x86_64/arch_thread_types.h | 6 + .../kernel/arch/x86_64/arch_user_debugger.h | 6 + .../platform/bios_ia32/platform_kernel_args.h | 2 +- .../private/system/arch/x86_64/arch_config.h | 15 ++ headers/private/system/arch/x86_64/arch_elf.h | 6 + headers/private/system/arch/x86_64/asm_defs.h | 17 +++ src/system/boot/Jamfile | 61 +++++---- src/system/boot/arch/arm/Jamfile | 2 +- src/system/boot/arch/m68k/Jamfile | 8 +- src/system/boot/arch/mipsel/Jamfile | 2 +- src/system/boot/arch/ppc/Jamfile | 2 +- src/system/boot/arch/x86/Jamfile | 2 +- src/system/boot/arch/x86_64/Jamfile | 30 ++++ src/system/boot/loader/Jamfile | 4 +- .../loader/file_systems/amiga_ffs/Jamfile | 2 +- .../boot/loader/file_systems/bfs/Jamfile | 2 +- .../boot/loader/file_systems/fat/Jamfile | 2 +- .../boot/loader/file_systems/hfs_plus/Jamfile | 2 +- .../boot/loader/file_systems/tarfs/Jamfile | 4 +- src/system/boot/loader/net/Jamfile | 2 +- src/system/boot/platform/amiga_m68k/Jamfile | 6 +- src/system/boot/platform/atari_m68k/Jamfile | 6 +- src/system/boot/platform/bios_ia32/Jamfile | 2 +- .../boot/platform/bios_ia32/interrupts.cpp | 2 +- src/system/boot/platform/cfe/Jamfile | 2 +- src/system/boot/platform/cfe/arch/ppc/Jamfile | 2 +- src/system/boot/platform/generic/Jamfile | 2 +- src/system/boot/platform/openfirmware/Jamfile | 2 +- .../platform/openfirmware/arch/ppc/Jamfile | 2 +- src/system/boot/platform/pxe_ia32/Jamfile | 2 +- .../boot/platform/raspberrypi_arm/Jamfile | 2 +- .../boot/platform/routerboard_mipsel/Jamfile | 2 +- src/system/boot/platform/u-boot/Jamfile | 4 +- .../boot/platform/u-boot/arch/arm/Jamfile | 2 +- .../boot/platform/u-boot/arch/ppc/Jamfile | 2 +- .../ldscripts/x86_64/boot_loader_bios_ia32.ld | 33 +++++ .../ldscripts/x86_64/boot_loader_pxe_ia32.ld | 33 +++++ 48 files changed, 420 insertions(+), 66 deletions(-) create mode 100644 build/jam/BootRules create mode 100644 headers/private/kernel/arch/x86_64/arch_cpu.h create mode 100644 headers/private/kernel/arch/x86_64/arch_int.h create mode 100644 headers/private/kernel/arch/x86_64/arch_kernel.h create mode 100644 headers/private/kernel/arch/x86_64/arch_kernel_args.h create mode 100644 headers/private/kernel/arch/x86_64/arch_system_info.h create mode 100644 headers/private/kernel/arch/x86_64/arch_thread.h create mode 100644 headers/private/kernel/arch/x86_64/arch_thread_types.h create mode 100644 headers/private/kernel/arch/x86_64/arch_user_debugger.h create mode 100644 headers/private/system/arch/x86_64/arch_config.h create mode 100644 headers/private/system/arch/x86_64/arch_elf.h create mode 100644 headers/private/system/arch/x86_64/asm_defs.h create mode 100644 src/system/boot/arch/x86_64/Jamfile create mode 100644 src/system/ldscripts/x86_64/boot_loader_bios_ia32.ld create mode 100644 src/system/ldscripts/x86_64/boot_loader_pxe_ia32.ld diff --git a/Jamrules b/Jamrules index c8f6182603..711d802298 100644 --- a/Jamrules +++ b/Jamrules @@ -44,6 +44,7 @@ include [ FDirName $(HAIKU_BUILD_RULES_DIR) DocumentationRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) FileRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) HeadersRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) KernelRules ] ; +include [ FDirName $(HAIKU_BUILD_RULES_DIR) BootRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) ImageRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) CDRules ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) MainBuildRules ] ; diff --git a/build/jam/BootRules b/build/jam/BootRules new file mode 100644 index 0000000000..fde7d54313 --- /dev/null +++ b/build/jam/BootRules @@ -0,0 +1,129 @@ + +rule SetupBoot +{ + # Usage SetupBoot : : ; + # + # - Ideally sources, otherwise HDRSEARCH can not be + # set for the sources and the sources some header + # dependencies might be missing. + + local sources = [ FGristFiles $(1) ] ; + local objects = $(sources:S=$(SUFOBJ)) ; + + # add private kernel headers + if $(3) != false { + SourceSysHdrs $(sources) : $(TARGET_PRIVATE_KERNEL_HEADERS) ; + } + + local object ; + for object in $(objects) { + # add boot flags for the object + ObjectCcFlags $(object) : $(TARGET_BOOT_CCFLAGS) $(2) ; + ObjectC++Flags $(object) : $(TARGET_BOOT_C++FLAGS) $(2) ; + ObjectDefines $(object) : $(TARGET_KERNEL_DEFINES) ; + ASFLAGS on $(object) = $(TARGET_BOOT_CCFLAGS) ; + + # override warning flags + TARGET_WARNING_CCFLAGS on $(object) = $(TARGET_KERNEL_WARNING_CCFLAGS) ; + TARGET_WARNING_C++FLAGS on $(object) + = $(TARGET_KERNEL_WARNING_C++FLAGS) ; + } +} + +rule BootObjects +{ + SetupBoot $(1) : $(2) ; + Objects $(1) ; +} + +rule BootLd +{ + # BootLd : : : ; + + LINK on $(1) = $(TARGET_LD) ; + + LINKFLAGS on $(1) = $(4) ; + if $(3) { LINKFLAGS on $(1) += --script=$(3) ; } + + # Remove any preset LINKLIBS, but link against libgcc.a. Linking against + # libsupc++ is opt-out. + local libs ; + if ! [ on $(1) return HAIKU_NO_LIBSUPC++ ] { + libs += $(TARGET_BOOT_LIBSUPC++) ; + } + LINKLIBS on $(1) = $(libs) $(TARGET_BOOT_LIBGCC) ; + + # TODO: Do we really want to invoke SetupBoot here? The objects should + # have been compiled with BootObjects anyway, so we're doing that twice. + SetupBoot $(2) ; + + # Show that we depend on the libraries we need + LocalClean clean : $(1) ; + LocalDepends all : $(1) ; + Depends $(1) : $(2) ; + + MakeLocateDebug $(1) ; + + on $(1) XRes $(1) : $(RESFILES) ; + if ! [ on $(1) return $(DONT_USE_BEOS_RULES) ] { + SetType $(1) ; + MimeSet $(1) ; + SetVersion $(1) ; + } +} + +actions BootLd bind VERSION_SCRIPT +{ + $(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) \ + --version-script=$(VERSION_SCRIPT) +} + +rule BootMergeObject +{ + # BootMergeObject : : : ; + # Compiles source files and merges the object files to an object file. + # : Name of the object file to create. No grist will be added. + # : Sources to be compiled. Grist will be added. + # : Additional flags for compilation. + # : Object files or static libraries to be merged. No grist + # will be added. + # + + SetupBoot $(2) : $(3) ; + Objects $(2) ; + MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(4) ; + LINKFLAGS on $(1) += $(TARGET_BOOT_LINKFLAGS) ; +} + +rule BootStaticLibrary +{ + # Usage BootStaticLibrary : : ; + # This is designed to take a set of sources and libraries and create + # a file called lib.a + + SetupBoot $(2) : $(3) : false ; + Library $(1) : $(2) ; +} + +rule BootStaticLibraryObjects +{ + # Usage BootStaticLibrary : ; + # This is designed to take a set of sources and libraries and create + # a file called + + # Show that we depend on the libraries we need + SetupBoot $(2) ; + LocalClean clean : $(1) ; + LocalDepends all : $(1) ; + Depends $(1) : $(2) ; + + MakeLocateDebug $(1) ; +} + +actions BootStaticLibraryObjects +{ + # Force recreation of the archive to avoid build errors caused by + # stale dependencies after renaming or deleting object files. + $(RM) "$(1)" + $(HAIKU_AR) -r "$(1)" "$(2)" ; +} diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index dd4a91d91e..6a564e7ff9 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -159,10 +159,13 @@ if $(HAIKU_GCC_VERSION[1]) = 2 { HAIKU_C++ ?= $(HAIKU_CC) ; HAIKU_LINK = $(HAIKU_CC) ; HAIKU_LINKFLAGS = $(HAIKU_GCC_BASE_FLAGS) ; +HAIKU_BOOT_LINKFLAGS = ; HAIKU_HDRS = [ FStandardHeaders ] ; HAIKU_KERNEL_CCFLAGS = $(HAIKU_CCFLAGS) $(HAIKU_GCC_BASE_FLAGS) ; HAIKU_KERNEL_C++FLAGS = $(HAIKU_C++FLAGS) $(HAIKU_GCC_BASE_FLAGS) ; +HAIKU_BOOT_CCFLAGS = $(HAIKU_CCFLAGS) $(HAIKU_GCC_BASE_FLAGS) ; +HAIKU_BOOT_C++FLAGS = $(HAIKU_C++FLAGS) $(HAIKU_GCC_BASE_FLAGS) ; HAIKU_CCFLAGS += $(HAIKU_GCC_BASE_FLAGS) -nostdinc ; HAIKU_C++FLAGS += $(HAIKU_GCC_BASE_FLAGS) -nostdinc ; HAIKU_DEFINES = __HAIKU__ ; @@ -249,7 +252,6 @@ switch $(HAIKU_CPU) { } case x86_64 : { - HAIKU_DEFINES += __x86_64__ ; HAIKU_BOOT_PLATFORM = bios_ia32 ; HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB # offset in floppy image (>= sizeof(haiku_loader)) @@ -329,6 +331,8 @@ HAIKU_ASFLAGS = ; HAIKU_KERNEL_CCFLAGS += -finline -fno-builtin ; HAIKU_KERNEL_C++FLAGS += -finline -fno-builtin -fno-exceptions ; HAIKU_KERNEL_DEFINES += _KERNEL_MODE ; +HAIKU_BOOT_CCFLAGS += -finline -fno-builtin ; +HAIKU_BOOT_C++FLAGS += -finline -fno-builtin -fno-exceptions ; if $(HAIKU_GCC_VERSION[1]) >= 3 { HAIKU_KERNEL_C++FLAGS += -fno-use-cxa-atexit ; @@ -340,6 +344,8 @@ if $(HAIKU_GCC_VERSION[1]) >= 4 { if $(HAIKU_GCC_VERSION[2]) >= 3 { HAIKU_KERNEL_CCFLAGS += -ffreestanding ; HAIKU_KERNEL_C++FLAGS += -ffreestanding ; + HAIKU_BOOT_CCFLAGS += -ffreestanding ; + HAIKU_BOOT_C++FLAGS += -ffreestanding ; } } @@ -377,6 +383,15 @@ switch $(HAIKU_ARCH) { } case x86_64 : { + # Kernel lives in the top 2GB of the address space, use kernel code model. + HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel ; + HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel ; + + # Bootloader is 32-bit. + HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; + HAIKU_BOOT_CCFLAGS += -m32 ; + HAIKU_BOOT_C++FLAGS += -m32 ; + # Enable use of the gcc built-in atomic functions instead of atomic_*(). # The former are inlined and have thus less overhead. HAIKU_DEFINES += B_USE_BUILTIN_ATOMIC_FUNCTIONS ; @@ -962,6 +977,7 @@ local buildVars = KERNEL_CCFLAGS KERNEL_C++FLAGS KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS + BOOT_CCFLAGS BOOT_C++FLAGS BOOT_LINKFLAGS WARNING_CCFLAGS WARNING_C++FLAGS KERNEL_WARNING_CCFLAGS KERNEL_WARNING_C++FLAGS @@ -998,6 +1014,9 @@ if $(TARGET_PLATFORM) = haiku { TARGET_GCC_LIBGCC = $(HAIKU_GCC_LIBGCC) ; TARGET_GCC_LIBGCC_OBJECTS = $(HAIKU_GCC_LIBGCC_OBJECTS) ; + TARGET_BOOT_LIBGCC = $(HAIKU_BOOT_LIBGCC) ; + TARGET_BOOT_LIBSUPC++ = $(HAIKU_BOOT_LIBSUPC++) ; + TARGET_BOOT_PLATFORM ?= $(HAIKU_BOOT_PLATFORM) ; TARGET_BOOT_BOARD ?= $(HAIKU_BOOT_BOARD) ; @@ -1014,6 +1033,9 @@ if $(TARGET_PLATFORM) = haiku { TARGET_GCC_LIBGCC = ; TARGET_GCC_LIBGCC_OBJECTS = ; + TARGET_BOOT_LIBGCC = ; + TARGET_BOOT_LIBSUPC++ = ; + TARGET_BOOT_PLATFORM = ; TARGET_BOOT_BOARD = ; diff --git a/configure b/configure index 9d6ca5a3da..48911b31f3 100755 --- a/configure +++ b/configure @@ -242,6 +242,14 @@ standard_gcc_settings() fi ;; esac + + if [ "$targetArch" = "x86_64" ]; then + HAIKU_BOOT_LIBGCC=`$HAIKU_CC -m32 -print-libgcc-file-name` + HAIKU_BOOT_LIBSUPCXX=`$HAIKU_CC -m32 -print-file-name=libsupc++.a` + else + HAIKU_BOOT_LIBGCC=$HAIKU_GCC_LIBGCC + HAIKU_BOOT_LIBSUPCXX=$HAIKU_STATIC_LIBSUPCXX + fi } # set_default_value @@ -549,6 +557,9 @@ HAIKU_STATIC_LIBSUPC++ ?= ${HAIKU_STATIC_LIBSUPCXX} ; HAIKU_SHARED_LIBSUPC++ ?= ${HAIKU_SHARED_LIBSUPCXX} ; HAIKU_C++_HEADERS_DIR ?= ${HAIKU_CXX_HEADERS_DIR} ; +HAIKU_BOOT_LIBGCC ?= ${HAIKU_BOOT_LIBGCC} ; +HAIKU_BOOT_LIBSUPC++ ?= ${HAIKU_BOOT_LIBSUPCXX} ; + HAIKU_BUILD_ATTRIBUTES_DIR ?= ${HAIKU_BUILD_ATTRIBUTES_DIR} ; HAIKU_AR ?= ${HAIKU_AR} ; diff --git a/headers/private/kernel/arch/x86/apm.h b/headers/private/kernel/arch/x86/apm.h index 905ac0d249..675ed5a6be 100644 --- a/headers/private/kernel/arch/x86/apm.h +++ b/headers/private/kernel/arch/x86/apm.h @@ -7,7 +7,7 @@ #include -#include +#include struct kernel_args; diff --git a/headers/private/kernel/arch/x86_64/arch_cpu.h b/headers/private/kernel/arch/x86_64/arch_cpu.h new file mode 100644 index 0000000000..dfdfe6ad73 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_cpu.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_CPU_H +#define _KERNEL_ARCH_x86_64_CPU_H + +#include "../x86/arch_cpu.h" + +#endif /* _KERNEL_ARCH_x86_64_CPU_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_int.h b/headers/private/kernel/arch/x86_64/arch_int.h new file mode 100644 index 0000000000..cd1f423f15 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_int.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_INT_H +#define _KERNEL_ARCH_x86_64_INT_H + +#include "../x86/arch_int.h" + +#endif /* _KERNEL_ARCH_x86_64_INT_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h new file mode 100644 index 0000000000..40d55a3ac4 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_kernel.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_KERNEL_H +#define _KERNEL_ARCH_x86_64_KERNEL_H + +#include "../x86/arch_kernel.h" + +#endif /* _KERNEL_ARCH_x86_64_KERNEL_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel_args.h b/headers/private/kernel/arch/x86_64/arch_kernel_args.h new file mode 100644 index 0000000000..ecb2638c9a --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_kernel_args.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_KERNEL_ARGS_H +#define _KERNEL_ARCH_x86_64_KERNEL_ARGS_H + +#include "../x86/arch_kernel_args.h" + +#endif /* _KERNEL_ARCH_x86_64_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_system_info.h b/headers/private/kernel/arch/x86_64/arch_system_info.h new file mode 100644 index 0000000000..aeee330486 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_system_info.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_SYSTEM_INFO_H +#define _KERNEL_ARCH_x86_64_SYSTEM_INFO_H + +#include "../x86/arch_system_info.h" + +#endif /* _KERNEL_ARCH_x86_64_SYSTEM_INFO_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread.h b/headers/private/kernel/arch/x86_64/arch_thread.h new file mode 100644 index 0000000000..0776b2865c --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_thread.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_THREAD_H +#define _KERNEL_ARCH_x86_64_THREAD_H + +#include "../x86/arch_thread.h" + +#endif /* _KERNEL_ARCH_x86_64_THREAD_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread_types.h b/headers/private/kernel/arch/x86_64/arch_thread_types.h new file mode 100644 index 0000000000..f0dc013900 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_thread_types.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_THREAD_TYPES_H +#define _KERNEL_ARCH_x86_64_THREAD_TYPES_H + +#include "../x86/arch_thread_types.h" + +#endif /* _KERNEL_ARCH_x86_64_THREAD_TYPES_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_user_debugger.h b/headers/private/kernel/arch/x86_64/arch_user_debugger.h new file mode 100644 index 0000000000..9491ef5013 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_user_debugger.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_USER_DEBUGGER_H +#define _KERNEL_ARCH_x86_64_USER_DEBUGGER_H + +#include "../x86/arch_user_debugger.h" + +#endif /* _KERNEL_ARCH_x86_64_USER_DEBUGGER_H */ diff --git a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h index e66bebe92c..1b0ff82075 100644 --- a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h +++ b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h @@ -10,7 +10,7 @@ #endif -#include +#include #include diff --git a/headers/private/system/arch/x86_64/arch_config.h b/headers/private/system/arch/x86_64/arch_config.h new file mode 100644 index 0000000000..e788a335d0 --- /dev/null +++ b/headers/private/system/arch/x86_64/arch_config.h @@ -0,0 +1,15 @@ +/* + * Copyright 2004, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_x86_64_CONFIG_H +#define _KERNEL_ARCH_x86_64_CONFIG_H + +#define FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE unsigned long + +#define STACK_GROWS_DOWNWARDS + +//#define ATOMIC_FUNCS_ARE_SYSCALLS +//#define ATOMIC64_FUNCS_ARE_SYSCALLS + +#endif /* _KERNEL_ARCH_x86_64_CONFIG_H */ diff --git a/headers/private/system/arch/x86_64/arch_elf.h b/headers/private/system/arch/x86_64/arch_elf.h new file mode 100644 index 0000000000..410c003706 --- /dev/null +++ b/headers/private/system/arch/x86_64/arch_elf.h @@ -0,0 +1,6 @@ +#ifndef _KERNEL_ARCH_x86_64_ELF_H +#define _KERNEL_ARCH_x86_64_ELF_H + +#include "../x86/arch_elf.h" + +#endif /* _KERNEL_ARCH_x86_64_ELF_H */ diff --git a/headers/private/system/arch/x86_64/asm_defs.h b/headers/private/system/arch/x86_64/asm_defs.h new file mode 100644 index 0000000000..26d13c5691 --- /dev/null +++ b/headers/private/system/arch/x86_64/asm_defs.h @@ -0,0 +1,17 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SYSTEM_ARCH_X86_64_ASM_DEFS_H +#define SYSTEM_ARCH_X86_64_ASM_DEFS_H + + +#define SYMBOL(name) .global name; name +#define SYMBOL_END(name) 1: .size name, 1b - name +#define STATIC_FUNCTION(name) .type name, @function; name +#define FUNCTION(name) .global name; .type name, @function; name +#define FUNCTION_END(name) 1: .size name, 1b - name + + +#endif /* SYSTEM_ARCH_X86_64_ASM_DEFS_H */ + diff --git a/src/system/boot/Jamfile b/src/system/boot/Jamfile index ad8d151046..548883adb4 100644 --- a/src/system/boot/Jamfile +++ b/src/system/boot/Jamfile @@ -1,27 +1,37 @@ SubDir HAIKU_TOP src system boot ; -local librootFunctions = - abs.o - ctype.o - LocaleData.o - qsort.o - kernel_vsprintf.o - memcmp.o - memmove.o - strdup.o - strndup.o - strlen.o - strnlen.o - strcmp.o - strcasecmp.o - strncmp.o - strcat.o - strcpy.o - strlcat.o - strlcpy.o - strchr.o - strrchr.o - strtol.o +DEFINES += _BOOT_MODE ; + +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix string ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix stdlib ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) libroot posix locale ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) kernel lib ] ; + +UsePrivateHeaders [ FDirName libroot locale ] ; + +BootMergeObject boot_libroot.o : + abs.c + ctype.cpp + LocaleData.cpp + qsort.c + kernel_vsprintf.cpp + memcmp.c + memmove.c + strdup.c + strndup.cpp + strlen.cpp + strnlen.cpp + strcmp.c + strcasecmp.c + strncmp.c + strcat.c + strcpy.c + strlcat.c + strlcpy.c + strchr.c + strrchr.c + strtol.c + : -fno-pic ; local extraLinkerArgs = ; @@ -31,7 +41,7 @@ if $(HAIKU_BOARD_LOADER_BASE) { AddResources haiku_loader : boot_loader.rdef ; -KernelLd boot_loader_$(TARGET_BOOT_PLATFORM) : +BootLd boot_loader_$(TARGET_BOOT_PLATFORM) : boot_platform_$(TARGET_BOOT_PLATFORM).o boot_arch_$(TARGET_ARCH).o boot_loader.a @@ -47,9 +57,8 @@ KernelLd boot_loader_$(TARGET_BOOT_PLATFORM) : # needed by tarfs and video_splash.cpp boot_zlib.a - # libroot functions needed by the stage2 boot loader (compiled for the - # kernel) - $(librootFunctions:G=src!system!kernel!lib) + # libroot functions needed by the stage2 boot loader + boot_libroot.o : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/boot_loader_$(TARGET_BOOT_PLATFORM).ld : -Bstatic $(extraLinkerArgs) diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index cd3dd05748..d035c41a1f 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -22,7 +22,7 @@ local kernelLibArchObjects = memset.o ; -KernelMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_ARCH).o : debug_uart_8250.cpp arch_uart_8250.cpp arch_uart_pl011.cpp diff --git a/src/system/boot/arch/m68k/Jamfile b/src/system/boot/arch/m68k/Jamfile index a63209089a..349a350722 100644 --- a/src/system/boot/arch/m68k/Jamfile +++ b/src/system/boot/arch/m68k/Jamfile @@ -13,7 +13,7 @@ local kernelLibArchObjects = memset.o ; -KernelMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_ARCH).o : arch_elf.cpp $(librootArchObjects) : -fno-pic @@ -21,17 +21,17 @@ KernelMergeObject boot_arch_$(TARGET_ARCH).o : $(kernelLibArchObjects) ; -KernelMergeObject boot_arch_$(TARGET_ARCH)_030.o : +BootMergeObject boot_arch_$(TARGET_ARCH)_030.o : mmu_030.cpp : -fno-pic -Wno-unused -m68030 ; -KernelMergeObject boot_arch_$(TARGET_ARCH)_040.o : +BootMergeObject boot_arch_$(TARGET_ARCH)_040.o : mmu_040.cpp : -fno-pic -Wno-unused -m68040 ; -KernelMergeObject boot_arch_$(TARGET_ARCH)_060.o : +BootMergeObject boot_arch_$(TARGET_ARCH)_060.o : mmu_060.cpp : -fno-pic -Wno-unused -m68060 ; diff --git a/src/system/boot/arch/mipsel/Jamfile b/src/system/boot/arch/mipsel/Jamfile index 55f63e6d73..33f0198b1d 100644 --- a/src/system/boot/arch/mipsel/Jamfile +++ b/src/system/boot/arch/mipsel/Jamfile @@ -8,7 +8,7 @@ local kernelLibArchObjects = memset.o ; -KernelMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_ARCH).o : arch_elf.cpp : # additional flags : diff --git a/src/system/boot/arch/ppc/Jamfile b/src/system/boot/arch/ppc/Jamfile index c2b817b54c..07ad229e62 100644 --- a/src/system/boot/arch/ppc/Jamfile +++ b/src/system/boot/arch/ppc/Jamfile @@ -15,7 +15,7 @@ local kernelLibArchObjects = memset.o ; -KernelMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_ARCH).o : debug_uart_8250.cpp arch_uart_8250.cpp arch_elf.cpp diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index 7315dc73fe..21eb0ac506 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -18,7 +18,7 @@ local kernelLibArchObjects = byteorder.o ; -KernelMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_ARCH).o : $(kernelArchSources) $(kernelLibArchSources) : # additional flags diff --git a/src/system/boot/arch/x86_64/Jamfile b/src/system/boot/arch/x86_64/Jamfile new file mode 100644 index 0000000000..dae289606e --- /dev/null +++ b/src/system/boot/arch/x86_64/Jamfile @@ -0,0 +1,30 @@ +SubDir HAIKU_TOP src system boot arch x86_64 ; + +DEFINES += _BOOT_MODE ; + +local kernelArchSources = + arch_elf.cpp + cpuid.S +; + +local kernelLibArchSources = + arch_string.S +; + +local librootOsArchSources = + byteorder.S +; + +BootMergeObject boot_arch_$(TARGET_ARCH).o : + $(kernelArchSources) + $(kernelLibArchSources) + $(librootOsArchSources) + : # additional flags +; + +SEARCH on [ FGristFiles $(kernelArchSources) ] + = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; +SEARCH on [ FGristFiles $(kernelLibArchSources) ] + = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; +SEARCH on [ FGristFiles $(librootOsArchSources) ] + = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index 671ca94580..1cb962c7d7 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -50,7 +50,7 @@ UsePrivateHeaders shared storage ; SubDirC++Flags $(defines) -fno-rtti ; } -KernelStaticLibrary boot_loader : +BootStaticLibrary boot_loader : elf.cpp heap.cpp kernel_args.cpp @@ -81,7 +81,7 @@ KernelStaticLibrary boot_loader : # The partition support is built in an extra static library # so that only the ones that are used will be included. -KernelStaticLibrary boot_partitions : +BootStaticLibrary boot_partitions : FileMapDisk.cpp amiga_rdb.cpp apple.cpp diff --git a/src/system/boot/loader/file_systems/amiga_ffs/Jamfile b/src/system/boot/loader/file_systems/amiga_ffs/Jamfile index 222c7755b8..1b2d8bbc27 100644 --- a/src/system/boot/loader/file_systems/amiga_ffs/Jamfile +++ b/src/system/boot/loader/file_systems/amiga_ffs/Jamfile @@ -8,7 +8,7 @@ UsePrivateHeaders kernel storage ; SubDirC++Flags -fno-rtti ; -KernelStaticLibrary boot_amiga_ffs : +BootStaticLibrary boot_amiga_ffs : amiga_ffs.cpp Volume.cpp Directory.cpp diff --git a/src/system/boot/loader/file_systems/bfs/Jamfile b/src/system/boot/loader/file_systems/bfs/Jamfile index f5840e9e48..e91cf720d1 100644 --- a/src/system/boot/loader/file_systems/bfs/Jamfile +++ b/src/system/boot/loader/file_systems/bfs/Jamfile @@ -10,7 +10,7 @@ local defines = [ FDefines _BOOT_MODE ] ; SubDirCcFlags $(defines) ; SubDirC++Flags -fno-rtti $(defines) ; -KernelStaticLibrary boot_bfs : +BootStaticLibrary boot_bfs : bfs.cpp Directory.cpp File.cpp diff --git a/src/system/boot/loader/file_systems/fat/Jamfile b/src/system/boot/loader/file_systems/fat/Jamfile index 69aee03778..52de886b8c 100644 --- a/src/system/boot/loader/file_systems/fat/Jamfile +++ b/src/system/boot/loader/file_systems/fat/Jamfile @@ -13,7 +13,7 @@ local defines = [ FDefines _BOOT_MODE ] ; SubDirCcFlags $(defines) ; SubDirC++Flags -fno-rtti $(defines) ; -KernelStaticLibrary boot_fatfs : +BootStaticLibrary boot_fatfs : fatfs.cpp Volume.cpp CachedBlock.cpp diff --git a/src/system/boot/loader/file_systems/hfs_plus/Jamfile b/src/system/boot/loader/file_systems/hfs_plus/Jamfile index 9a02d8a6ff..13bbb378ac 100644 --- a/src/system/boot/loader/file_systems/hfs_plus/Jamfile +++ b/src/system/boot/loader/file_systems/hfs_plus/Jamfile @@ -6,7 +6,7 @@ UsePrivateHeaders kernel storage ; SubDirC++Flags -fno-rtti ; -KernelStaticLibrary boot_hfs_plus : +BootStaticLibrary boot_hfs_plus : hfs_plus.cpp : -fno-pic ; diff --git a/src/system/boot/loader/file_systems/tarfs/Jamfile b/src/system/boot/loader/file_systems/tarfs/Jamfile index 0b7008aa77..4e7f4793d3 100644 --- a/src/system/boot/loader/file_systems/tarfs/Jamfile +++ b/src/system/boot/loader/file_systems/tarfs/Jamfile @@ -14,7 +14,7 @@ SubDirC++Flags -fno-rtti $(defines) ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src libs zlib ] ; -KernelStaticLibrary boot_zlib : +BootStaticLibrary boot_zlib : inflate.c inffast.c inftrees.c @@ -25,7 +25,7 @@ KernelStaticLibrary boot_zlib : ; -KernelStaticLibrary boot_tarfs : +BootStaticLibrary boot_tarfs : tarfs.cpp : -fno-pic ; diff --git a/src/system/boot/loader/net/Jamfile b/src/system/boot/loader/net/Jamfile index dda66c0fa7..5bb8291a3f 100644 --- a/src/system/boot/loader/net/Jamfile +++ b/src/system/boot/loader/net/Jamfile @@ -12,7 +12,7 @@ if $(TARGET_ARCH) = ppc { iscsi = iSCSITarget.cpp ; } -KernelStaticLibrary boot_net : +BootStaticLibrary boot_net : ARP.cpp ChainBuffer.cpp Ethernet.cpp diff --git a/src/system/boot/platform/amiga_m68k/Jamfile b/src/system/boot/platform/amiga_m68k/Jamfile index 9f223dd3cc..b867ef7f6f 100644 --- a/src/system/boot/platform/amiga_m68k/Jamfile +++ b/src/system/boot/platform/amiga_m68k/Jamfile @@ -19,13 +19,13 @@ UsePrivateHeaders [ FDirName storage ] ; #SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_amiga_m68k_shell.o : +BootMergeObject boot_platform_amiga_m68k_shell.o : shell.S : -Wa,--pcrel ; -KernelMergeObject boot_platform_amiga_m68k_other.o : +BootMergeObject boot_platform_amiga_m68k_other.o : # shell.S start.cpp rom_calls.cpp @@ -54,7 +54,7 @@ KernelMergeObject boot_platform_amiga_m68k_other.o : ; -KernelMergeObject boot_platform_amiga_m68k.o : +BootMergeObject boot_platform_amiga_m68k.o : : : boot_platform_amiga_m68k_shell.o boot_platform_amiga_m68k_other.o diff --git a/src/system/boot/platform/atari_m68k/Jamfile b/src/system/boot/platform/atari_m68k/Jamfile index 287666bf85..b71de5a25d 100644 --- a/src/system/boot/platform/atari_m68k/Jamfile +++ b/src/system/boot/platform/atari_m68k/Jamfile @@ -19,7 +19,7 @@ UsePrivateHeaders [ FDirName storage ] ; #SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_atari_m68k_shell.o : +BootMergeObject boot_platform_atari_m68k_shell.o : shell.S : -Wa,--pcrel ; @@ -30,7 +30,7 @@ KernelMergeObject boot_platform_atari_m68k_shell.o : # TODO: add 020+68851 support -KernelMergeObject boot_platform_atari_m68k_other.o : +BootMergeObject boot_platform_atari_m68k_other.o : # shell.S start.cpp toscalls.cpp @@ -59,7 +59,7 @@ KernelMergeObject boot_platform_atari_m68k_other.o : ; -KernelMergeObject boot_platform_atari_m68k.o : +BootMergeObject boot_platform_atari_m68k.o : : : boot_platform_atari_m68k_shell.o boot_platform_atari_m68k_other.o diff --git a/src/system/boot/platform/bios_ia32/Jamfile b/src/system/boot/platform/bios_ia32/Jamfile index 9219e5b392..6c0c273f88 100644 --- a/src/system/boot/platform/bios_ia32/Jamfile +++ b/src/system/boot/platform/bios_ia32/Jamfile @@ -17,7 +17,7 @@ UsePrivateHeaders [ FDirName storage ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_bios_ia32.o : +BootMergeObject boot_platform_bios_ia32.o : shell.S start.cpp debug.cpp diff --git a/src/system/boot/platform/bios_ia32/interrupts.cpp b/src/system/boot/platform/bios_ia32/interrupts.cpp index 3b4505c0a3..c5efc58ad5 100644 --- a/src/system/boot/platform/bios_ia32/interrupts.cpp +++ b/src/system/boot/platform/bios_ia32/interrupts.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include "debug.h" #include "keyboard.h" diff --git a/src/system/boot/platform/cfe/Jamfile b/src/system/boot/platform/cfe/Jamfile index 8114492e79..7f54c77414 100644 --- a/src/system/boot/platform/cfe/Jamfile +++ b/src/system/boot/platform/cfe/Jamfile @@ -6,7 +6,7 @@ UsePrivateHeaders [ FDirName graphics common ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_cfe.o : +BootMergeObject boot_platform_cfe.o : console.cpp debug.cpp devices.cpp diff --git a/src/system/boot/platform/cfe/arch/ppc/Jamfile b/src/system/boot/platform/cfe/arch/ppc/Jamfile index 14cc7e7567..f7408331d2 100644 --- a/src/system/boot/platform/cfe/arch/ppc/Jamfile +++ b/src/system/boot/platform/cfe/arch/ppc/Jamfile @@ -7,7 +7,7 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] SubDirC++Flags -fno-rtti ; -KernelStaticLibrary boot_platform_cfe_ppc : +BootStaticLibrary boot_platform_cfe_ppc : arch_mmu.cpp arch_cpu_asm.S arch_start_kernel.S diff --git a/src/system/boot/platform/generic/Jamfile b/src/system/boot/platform/generic/Jamfile index 0ca49679b0..fad4f47ad2 100644 --- a/src/system/boot/platform/generic/Jamfile +++ b/src/system/boot/platform/generic/Jamfile @@ -5,7 +5,7 @@ UsePrivateKernelHeaders ; SubDirC++Flags -D_BOOT_MODE -fno-rtti ; -KernelStaticLibrary boot_platform_generic : +BootStaticLibrary boot_platform_generic : text_menu.cpp video_blit.cpp video_splash.cpp diff --git a/src/system/boot/platform/openfirmware/Jamfile b/src/system/boot/platform/openfirmware/Jamfile index 227df039bf..43f2f2c765 100644 --- a/src/system/boot/platform/openfirmware/Jamfile +++ b/src/system/boot/platform/openfirmware/Jamfile @@ -6,7 +6,7 @@ UsePrivateHeaders [ FDirName graphics common ] ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_openfirmware.o : +BootMergeObject boot_platform_openfirmware.o : console.cpp debug.cpp devices.cpp diff --git a/src/system/boot/platform/openfirmware/arch/ppc/Jamfile b/src/system/boot/platform/openfirmware/arch/ppc/Jamfile index 651d61c6b5..a82fda7594 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/Jamfile +++ b/src/system/boot/platform/openfirmware/arch/ppc/Jamfile @@ -7,7 +7,7 @@ UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] SubDirC++Flags -fno-rtti ; -KernelStaticLibrary boot_platform_openfirmware_ppc : +BootStaticLibrary boot_platform_openfirmware_ppc : arch_mmu.cpp arch_cpu_asm.S arch_start_kernel.S diff --git a/src/system/boot/platform/pxe_ia32/Jamfile b/src/system/boot/platform/pxe_ia32/Jamfile index 73c75ebe35..fe59db7dab 100644 --- a/src/system/boot/platform/pxe_ia32/Jamfile +++ b/src/system/boot/platform/pxe_ia32/Jamfile @@ -45,7 +45,7 @@ local bios_ia32_edid_src = ; -KernelMergeObject boot_platform_pxe_ia32.o : +BootMergeObject boot_platform_pxe_ia32.o : pxe_stage2.S smp_trampoline.S pxe_bios.S diff --git a/src/system/boot/platform/raspberrypi_arm/Jamfile b/src/system/boot/platform/raspberrypi_arm/Jamfile index 179f0d5555..9b4b72ef39 100644 --- a/src/system/boot/platform/raspberrypi_arm/Jamfile +++ b/src/system/boot/platform/raspberrypi_arm/Jamfile @@ -19,7 +19,7 @@ UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOAR SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; -KernelMergeObject boot_platform_raspberrypi_arm.o : +BootMergeObject boot_platform_raspberrypi_arm.o : entry.S start.c console.cpp diff --git a/src/system/boot/platform/routerboard_mipsel/Jamfile b/src/system/boot/platform/routerboard_mipsel/Jamfile index 94f292ddd6..979e6fd6c4 100644 --- a/src/system/boot/platform/routerboard_mipsel/Jamfile +++ b/src/system/boot/platform/routerboard_mipsel/Jamfile @@ -23,7 +23,7 @@ local genericPlatformSources = # video_splash.cpp ; -KernelMergeObject boot_platform_routerboard_mipsel.o : +BootMergeObject boot_platform_routerboard_mipsel.o : console.cpp cpu.cpp debug.c diff --git a/src/system/boot/platform/u-boot/Jamfile b/src/system/boot/platform/u-boot/Jamfile index 17327b84d4..7d9ba932f0 100644 --- a/src/system/boot/platform/u-boot/Jamfile +++ b/src/system/boot/platform/u-boot/Jamfile @@ -29,7 +29,7 @@ local uImageFakeOS = "netbsd" ; SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; # First build the non arch dependent parts -KernelMergeObject boot_platform_u-boot_common.o : +BootMergeObject boot_platform_u-boot_common.o : start.cpp debug.cpp console.cpp @@ -48,7 +48,7 @@ KernelMergeObject boot_platform_u-boot_common.o : : boot_platform_generic.a ; -KernelMergeObject boot_platform_u-boot.o : +BootMergeObject boot_platform_u-boot.o : : : # must come first to have _start_* at correct locations boot_platform_u-boot_$(TARGET_ARCH).o diff --git a/src/system/boot/platform/u-boot/arch/arm/Jamfile b/src/system/boot/platform/u-boot/arch/arm/Jamfile index a81e46bc90..2bf09c10e5 100644 --- a/src/system/boot/platform/u-boot/arch/arm/Jamfile +++ b/src/system/boot/platform/u-boot/arch/arm/Jamfile @@ -8,7 +8,7 @@ UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOAR SubDirC++Flags -fno-rtti ; -KernelMergeObject boot_platform_u-boot_arm.o : +BootMergeObject boot_platform_u-boot_arm.o : # must come first to have _start_* at correct locations shell.S diff --git a/src/system/boot/platform/u-boot/arch/ppc/Jamfile b/src/system/boot/platform/u-boot/arch/ppc/Jamfile index ad93d5969d..46848e7d07 100644 --- a/src/system/boot/platform/u-boot/arch/ppc/Jamfile +++ b/src/system/boot/platform/u-boot/arch/ppc/Jamfile @@ -8,7 +8,7 @@ UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOAR SubDirC++Flags -fno-rtti ; -KernelMergeObject boot_platform_u-boot_ppc.o : +BootMergeObject boot_platform_u-boot_ppc.o : # must come first to have _start_* at correct locations shell.S diff --git a/src/system/ldscripts/x86_64/boot_loader_bios_ia32.ld b/src/system/ldscripts/x86_64/boot_loader_bios_ia32.ld new file mode 100644 index 0000000000..6cc9efd4a6 --- /dev/null +++ b/src/system/ldscripts/x86_64/boot_loader_bios_ia32.ld @@ -0,0 +1,33 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) + +ENTRY(_start) +SECTIONS +{ + . = 0x10000; + + /* text/read-only data */ + .text : { *(.text .gnu.linkonce.t.*) } + + . = ALIGN(0x4); + __ctor_list = .; + .ctors : { *(.ctors) } + __ctor_end = .; + + .rodata : { *(.rodata .rodata.*) } + + /* writable data */ + . = ALIGN(0x1000); + __data_start = .; + .data : { *(.data .gnu.linkonce.d.*) } + + /* uninitialized data (in same segment as writable data) */ + __bss_start = .; + .bss : { *(.bss) } + + . = ALIGN(0x1000); + _end = . ; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame .dtors .stab .stabstr .debug*) } +} diff --git a/src/system/ldscripts/x86_64/boot_loader_pxe_ia32.ld b/src/system/ldscripts/x86_64/boot_loader_pxe_ia32.ld new file mode 100644 index 0000000000..6cc9efd4a6 --- /dev/null +++ b/src/system/ldscripts/x86_64/boot_loader_pxe_ia32.ld @@ -0,0 +1,33 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) + +ENTRY(_start) +SECTIONS +{ + . = 0x10000; + + /* text/read-only data */ + .text : { *(.text .gnu.linkonce.t.*) } + + . = ALIGN(0x4); + __ctor_list = .; + .ctors : { *(.ctors) } + __ctor_end = .; + + .rodata : { *(.rodata .rodata.*) } + + /* writable data */ + . = ALIGN(0x1000); + __data_start = .; + .data : { *(.data .gnu.linkonce.d.*) } + + /* uninitialized data (in same segment as writable data) */ + __bss_start = .; + .bss : { *(.bss) } + + . = ALIGN(0x1000); + _end = . ; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame .dtors .stab .stabstr .debug*) } +} From 2f3e39bebf0690998c95bce82b26a6435d8bf053 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 11 Jun 2012 12:09:36 +0100 Subject: [PATCH 002/273] Fixed copyright date on arch_config.h. --- headers/private/system/arch/x86_64/arch_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headers/private/system/arch/x86_64/arch_config.h b/headers/private/system/arch/x86_64/arch_config.h index e788a335d0..2c4e64320c 100644 --- a/headers/private/system/arch/x86_64/arch_config.h +++ b/headers/private/system/arch/x86_64/arch_config.h @@ -1,5 +1,5 @@ /* - * Copyright 2004, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_ARCH_x86_64_CONFIG_H From 0d916c34c4d2c15f233fac8ffefa8ee41f074b18 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 11 Jun 2012 12:49:14 +0100 Subject: [PATCH 003/273] x86_64: added linker script for the kernel. * Based on the x86 one, changes made to match the default GCC x86_64 linker script and correct kernel load address added. * Not tested yet as the kernel doesn't fully compile. --- src/system/ldscripts/x86_64/kernel.ld | 55 +++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/system/ldscripts/x86_64/kernel.ld diff --git a/src/system/ldscripts/x86_64/kernel.ld b/src/system/ldscripts/x86_64/kernel.ld new file mode 100644 index 0000000000..f3db82d1d8 --- /dev/null +++ b/src/system/ldscripts/x86_64/kernel.ld @@ -0,0 +1,55 @@ +OUTPUT_FORMAT("elf64-x86-64") +OUTPUT_ARCH("i386:x86-64") + +ENTRY(_start) +SECTIONS +{ + . = 0xFFFFFF8000000000 + SIZEOF_HEADERS; + + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rela.got : { *(.rela.got) } + .rela.ctors : { *(.rela.ctors) } + .rela.dtors : { *(.rela.dtors) } + .rela.init : { *(.rela.init) } + .rela.fini : { *(.rela.fini) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x90909090 + .plt : { *(.plt) } + + /* text/read-only data */ + .text : { *(.text .text.* .gnu.linkonce.t.*) } =0x90909090 + + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + + /* writable data */ + . = ALIGN(0x1000); + __data_start = .; + .data : { *(.data .data.* .gnu.linkonce.d.*) } + + . = ALIGN(0x4); + __ctor_list = .; + .ctors : { *(.ctors) } + __ctor_end = .; + __dtor_list = .; + .dtors : { *(.dtors) } + __dtor_end = .; + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + + /* uninitialized data (in same segment as writable data) */ + __bss_start = .; + .bss : { *(.bss .bss.* .gnu.linkonce.b.*) } + + . = ALIGN(0x1000); + _end = . ; + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame) } +} From 23d878482ed22e55dad6d1fca1df7bea42eb157c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 13 Jun 2012 17:00:57 +0100 Subject: [PATCH 004/273] Made *_addr_t {,un}signed long rather than long long on x86_64. * long is 64-bit on x86_64. * Makes addr_t compatible with size_t. --- headers/config/types.h | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/headers/config/types.h b/headers/config/types.h index 84209791b5..f0140a01b9 100644 --- a/headers/config/types.h +++ b/headers/config/types.h @@ -38,20 +38,20 @@ typedef __haiku_std_int64 __haiku_int64; typedef __haiku_std_uint64 __haiku_uint64; /* address types */ -#ifdef __HAIKU_ARCH_64_BIT - typedef __haiku_int64 __haiku_saddr_t; - typedef __haiku_uint64 __haiku_addr_t; -#else - typedef __haiku_int32 __haiku_saddr_t; - typedef __haiku_uint32 __haiku_addr_t; -#endif +typedef signed long int __haiku_saddr_t; +typedef unsigned long int __haiku_addr_t; #ifdef __HAIKU_ARCH_PHYSICAL_64_BIT - typedef __haiku_int64 __haiku_phys_saddr_t; - typedef __haiku_uint64 __haiku_phys_addr_t; +# if __HAIKU_ARCH_64_BIT + typedef signed long int __haiku_phys_saddr_t; + typedef unsigned long int __haiku_phys_addr_t; +# else + typedef signed long long __haiku_phys_saddr_t; + typedef unsigned long long __haiku_phys_addr_t; +# endif #else - typedef __haiku_int32 __haiku_phys_saddr_t; - typedef __haiku_uint32 __haiku_phys_addr_t; + typedef signed long int __haiku_phys_saddr_t; + typedef unsigned long int __haiku_phys_addr_t; #endif /* address type limits */ @@ -85,16 +85,12 @@ typedef __haiku_std_uint64 __haiku_uint64; #endif #define __HAIKU_PRI_PREFIX_64 __HAIKU_STD_PRI_PREFIX_64 -#ifdef __HAIKU_ARCH_64_BIT -# define __HAIKU_PRI_PREFIX_ADDR __HAIKU_PRI_PREFIX_64 -#else -# define __HAIKU_PRI_PREFIX_ADDR __HAIKU_PRI_PREFIX_32 -#endif +#define __HAIKU_PRI_PREFIX_ADDR "l" -#ifdef __HAIKU_ARCH_PHYSICAL_64_BIT -# define __HAIKU_PRI_PREFIX_PHYS_ADDR __HAIKU_PRI_PREFIX_64 +#if __HAIKU_ARCH_PHYSICAL_64_BIT && !__HAIKU_ARCH_64_BIT +# define __HAIKU_PRI_PREFIX_PHYS_ADDR "ll" #else -# define __HAIKU_PRI_PREFIX_PHYS_ADDR __HAIKU_PRI_PREFIX_32 +# define __HAIKU_PRI_PREFIX_PHYS_ADDR "l" #endif From 0e88a887b4a9ecaaf1062078d9ca9bfca78fcf3a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 13 Jun 2012 17:42:46 +0100 Subject: [PATCH 005/273] First round of 64-bit safety fixes in the kernel. * Most of this is incorrect printf format strings. Changed all strings causing errors to use the B_PRI* format string definitions, which means the strings should be correct across all platforms. * Some other fixes for errors, casts required, etc. --- src/system/kernel/cache/block_cache.cpp | 149 +++++++++++---------- src/system/kernel/cache/file_cache.cpp | 8 +- src/system/kernel/cache/file_map.cpp | 22 +-- src/system/kernel/condition_variable.cpp | 4 +- src/system/kernel/elf.cpp | 3 + src/system/kernel/heap.cpp | 50 +++---- src/system/kernel/image.cpp | 13 +- src/system/kernel/int.cpp | 2 +- src/system/kernel/low_resource_manager.cpp | 10 +- src/system/kernel/main.cpp | 2 +- src/system/kernel/module.cpp | 11 +- src/system/kernel/port.cpp | 26 ++-- src/system/kernel/real_time_clock.cpp | 2 +- src/system/kernel/sem.cpp | 34 ++--- src/system/kernel/smp.cpp | 32 ++--- src/system/kernel/system_info.cpp | 17 ++- 16 files changed, 202 insertions(+), 183 deletions(-) diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index b49bf6e902..6a02dad69d 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -290,8 +290,8 @@ public: virtual void AddDump(TraceOutput& out) { - out.Print("block cache %p, %s %Ld, %c%c%c transaction %ld " - "(previous id %ld)\n", fCache, _Action(), fBlockNumber, + out.Print("block cache %p, %s %" B_PRIu64 ", %c%c%c transaction %" B_PRId32 + " (previous id %" B_PRId32 ")\n", fCache, _Action(), fBlockNumber, fIsDirty ? 'd' : '-', fHasOriginal ? 'o' : '-', fHasParent ? 'p' : '-', fTransactionID, fPreviousID); } @@ -388,7 +388,7 @@ public: virtual void AddDump(TraceOutput& out) { - out.Print("block cache %p, error %Ld, %s%s%s", + out.Print("block cache %p, error %" B_PRIu64 ", %s%s%s", fCache, fBlockNumber, fMessage, fStatus != B_OK ? ": " : "", fStatus != B_OK ? strerror(fStatus) : ""); } @@ -430,7 +430,7 @@ public: virtual void AddDump(TraceOutput& out) { - out.Print("block cache %p, block %Ld, data %c%c%c: %s", + out.Print("block cache %p, block %" B_PRIu64 ", data %c%c%c: %s", fCache, fBlockNumber, fCurrent != NULL ? 'c' : '-', fParent != NULL ? 'p' : '-', fOriginal != NULL ? 'o' : '-', fMessage); @@ -456,7 +456,7 @@ public: void DumpBlock(uint32 which, uint32 offset, uint32 size) { if (offset > fSize) { - kprintf("invalid offset (block size %lu)\n", fSize); + kprintf("invalid offset (block size %" B_PRIu32 ")\n", fSize); return; } if (offset + size > fSize) @@ -477,7 +477,7 @@ public: } else return; - kprintf("%s: offset %lu, %lu bytes\n", label, offset, size); + kprintf("%s: offset %" B_PRIu32 ", %" B_PRIu32 " bytes\n", label, offset, size); static const uint32 kBlockSize = 16; data += offset; @@ -485,7 +485,7 @@ public: for (uint32 i = 0; i < size;) { int start = i; - kprintf(" %04lx ", i); + kprintf(" %04" B_PRIx32 " ", i); for (; i < start + kBlockSize; i++) { if (!(i % 4)) kprintf(" "); @@ -559,9 +559,9 @@ public: virtual void AddDump(TraceOutput& out) { - out.Print("block cache %p, %s transaction %p (id %ld)%s" - ", %ld/%ld blocks", fCache, fLabel, fTransaction, fID, - fSub ? " sub" : "", fNumBlocks, fSubNumBlocks); + out.Print("block cache %p, %s transaction %p (id %" B_PRId32 ")%s" + ", %" B_PRId32 "/%" B_PRId32 " blocks", fCache, fLabel, fTransaction, + fID, fSub ? " sub" : "", fNumBlocks, fSubNumBlocks); } private: @@ -591,8 +591,8 @@ public: virtual void AddDump(TraceOutput& out) { - out.Print("block cache %p, detach transaction %p (id %ld)" - "from transaction %p (id %ld)%s", + out.Print("block cache %p, detach transaction %p (id %" B_PRId32 ")" + "from transaction %p (id %" B_PRId32 ")%s", fCache, fNewTransaction, fNewID, fTransaction, fID, fSub ? " sub" : ""); } @@ -639,9 +639,9 @@ public: virtual void AddDump(TraceOutput& out) { out.Print("block cache %p, abort transaction " - "%p (id %ld), blocks", fCache, fTransaction, fID); + "%p (id %" B_PRId32 "), blocks", fCache, fTransaction, fID); for (int32 i = 0; i < fNumBlocks && !out.IsFull(); i++) - out.Print(" %Ld", fBlocks[i]); + out.Print(" %" B_PRIdOFF, fBlocks[i]); } #if KTRACE_PRINTF_STACK_TRACE @@ -1200,7 +1200,7 @@ BlockWriter::_WriteBlock(cached_block* block) { ASSERT(block->busy_writing); - TRACE(("BlockWriter::_WriteBlock(block %Ld)\n", block->block_number)); + TRACE(("BlockWriter::_WriteBlock(block %" B_PRIdOFF ")\n", block->block_number)); TB(Write(fCache, block)); TB2(BlockData(fCache, block, "before write")); @@ -1211,7 +1211,7 @@ BlockWriter::_WriteBlock(cached_block* block) if (written != (ssize_t)blockSize) { TB(Error(fCache, block->block_number, "write failed", written)); - FATAL(("could not write back block %Ld (%s)\n", block->block_number, + FATAL(("could not write back block %" B_PRIdOFF " (%s)\n", block->block_number, strerror(errno))); if (written < 0) return errno; @@ -1253,7 +1253,7 @@ BlockWriter::_BlockDone(cached_block* block, hash_iterator* iterator) // Has the previous transation been finished with that write? if (--previous->num_blocks == 0) { - TRACE(("cache transaction %ld finished!\n", previous->id)); + TRACE(("cache transaction %" B_PRId32 " finished!\n", previous->id)); T(Action("written", fCache, previous)); notify_transaction_listeners(fCache, previous, @@ -1394,7 +1394,7 @@ block_cache::FreeBlock(cached_block* block) Free(block->current_data); if (block->original_data != NULL || block->parent_data != NULL) { - panic("block_cache::FreeBlock(): %Ld, original %p, parent %p\n", + panic("block_cache::FreeBlock(): %" B_PRIdOFF ", original %p, parent %p\n", block->block_number, block->original_data, block->parent_data); } @@ -1478,7 +1478,7 @@ block_cache::RemoveUnusedBlocks(int32 count, int32 minSecondsOld) continue; TB(Flush(this, block)); - TRACE((" remove block %Ld, last accessed %" B_PRId32 "\n", + TRACE((" remove block %" B_PRIdOFF ", last accessed %" B_PRId32 "\n", block->block_number, block->last_accessed)); // this can only happen if no transactions are used @@ -1533,7 +1533,7 @@ block_cache::DiscardBlock(cached_block* block) void block_cache::_LowMemoryHandler(void* data, uint32 resources, int32 level) { - TRACE(("block_cache: low memory handler called with level %ld\n", level)); + TRACE(("block_cache: low memory handler called with level %" B_PRId32 "\n", level)); // free some blocks according to the low memory state // (if there is enough memory left, we don't free any) @@ -1573,8 +1573,8 @@ block_cache::_LowMemoryHandler(void* data, uint32 resources, int32 level) cache->RemoveUnusedBlocks(free, secondsOld); - TRACE(("block_cache::_LowMemoryHandler(): %p: unused: %lu -> %lu\n", cache, - oldUnused, cache->unused_block_count)); + TRACE(("block_cache::_LowMemoryHandler(): %p: unused: %" B_PRIu32 " -> %" B_PRIu32 "\n", + cache, oldUnused, cache->unused_block_count)); } @@ -1775,7 +1775,7 @@ static void put_cached_block(block_cache* cache, off_t blockNumber) { if (blockNumber < 0 || blockNumber >= cache->max_blocks) { - panic("put_cached_block: invalid block number %lld (max %lld)", + panic("put_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); } @@ -1806,7 +1806,7 @@ get_cached_block(block_cache* cache, off_t blockNumber, bool* _allocated, ASSERT_LOCKED_MUTEX(&cache->lock); if (blockNumber < 0 || blockNumber >= cache->max_blocks) { - panic("get_cached_block: invalid block number %lld (max %lld)", + panic("get_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); return NULL; } @@ -1831,7 +1831,7 @@ retry: } if (block->unused) { - //TRACE(("remove block %Ld from unused\n", blockNumber)); + //TRACE(("remove block %" B_PRIdOFF " from unused\n", blockNumber)); block->unused = false; cache->unused_blocks.Remove(block); cache->unused_block_count--; @@ -1852,7 +1852,7 @@ retry: cache->RemoveBlock(block); TB(Error(cache, blockNumber, "read failed", bytesRead)); - FATAL(("could not read block %Ld: bytesRead: %ld, error: %s\n", + FATAL(("could not read block %" B_PRIdOFF ": bytesRead: %zd, error: %s\n", blockNumber, bytesRead, strerror(errno))); return NULL; } @@ -1879,11 +1879,11 @@ static void* get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, off_t length, int32 transactionID, bool cleared) { - TRACE(("get_writable_cached_block(blockNumber = %Ld, transaction = %ld)\n", + TRACE(("get_writable_cached_block(blockNumber = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n", blockNumber, transactionID)); if (blockNumber < 0 || blockNumber >= cache->max_blocks) { - panic("get_writable_cached_block: invalid block number %lld (max %lld)", + panic("get_writable_cached_block: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); } @@ -1927,7 +1927,8 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, if (transaction != NULL && transaction->id != transactionID) { // TODO: we have to wait here until the other transaction is done. // Maybe we should even panic, since we can't prevent any deadlocks. - panic("get_writable_cached_block(): asked to get busy writable block (transaction %ld)\n", block->transaction->id); + panic("get_writable_cached_block(): asked to get busy writable block (transaction %" B_PRId32 ")\n", + block->transaction->id); put_cached_block(cache, block); return NULL; } @@ -1935,7 +1936,7 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, // get new transaction transaction = lookup_transaction(cache, transactionID); if (transaction == NULL) { - panic("get_writable_cached_block(): invalid transaction %ld!\n", + panic("get_writable_cached_block(): invalid transaction %" B_PRId32 "!\n", transactionID); put_cached_block(cache, block); return NULL; @@ -2025,7 +2026,8 @@ get_writable_cached_block(block_cache* cache, off_t blockNumber, off_t base, static void dump_block(cached_block* block) { - kprintf("%08lx %9Ld %08lx %08lx %08lx %5ld %6ld %c%c%c%c%c%c %08lx %08lx\n", + kprintf("%08lx %9" B_PRIdOFF " %08lx %08lx %08lx %5" B_PRId32 " %6" B_PRId32 + " %c%c%c%c%c%c %08lx %08lx\n", (addr_t)block, block->block_number, (addr_t)block->current_data, (addr_t)block->original_data, (addr_t)block->parent_data, block->ref_count, block->LastAccess(), @@ -2047,8 +2049,8 @@ dump_block_long(cached_block* block) #if BLOCK_CACHE_DEBUG_CHANGED kprintf(" compare data: %p\n", block->compare); #endif - kprintf(" ref_count: %ld\n", block->ref_count); - kprintf(" accessed: %ld\n", block->LastAccess()); + kprintf(" ref_count: %" B_PRId32 "\n", block->ref_count); + kprintf(" accessed: %" B_PRId32 "\n", block->LastAccess()); kprintf(" flags: "); if (block->busy_reading) kprintf(" busy_reading"); @@ -2064,15 +2066,15 @@ dump_block_long(cached_block* block) kprintf(" discard"); kprintf("\n"); if (block->transaction != NULL) { - kprintf(" transaction: %p (%ld)\n", block->transaction, + kprintf(" transaction: %p (%" B_PRId32 ")\n", block->transaction, block->transaction->id); if (block->transaction_next != NULL) { - kprintf(" next in transaction: %Ld\n", + kprintf(" next in transaction: %" B_PRIdOFF "\n", block->transaction_next->block_number); } } if (block->previous_transaction != NULL) { - kprintf(" previous transaction: %p (%ld)\n", + kprintf(" previous transaction: %p (%" B_PRId32 ")\n", block->previous_transaction, block->previous_transaction->id); } @@ -2138,20 +2140,20 @@ dump_cache(int argc, char** argv) if (block != NULL) dump_block_long(block); else - kprintf("block %Ld not found\n", blockNumber); + kprintf("block %" B_PRIdOFF " not found\n", blockNumber); return 0; } kprintf("BLOCK CACHE: %p\n", cache); kprintf(" fd: %d\n", cache->fd); - kprintf(" max_blocks: %Ld\n", cache->max_blocks); - kprintf(" block_size: %lu\n", cache->block_size); - kprintf(" next_transaction_id: %ld\n", cache->next_transaction_id); + kprintf(" max_blocks: %" B_PRIdOFF "\n", cache->max_blocks); + kprintf(" block_size: %zu\n", cache->block_size); + kprintf(" next_transaction_id: %" B_PRId32 "\n", cache->next_transaction_id); kprintf(" buffer_cache: %p\n", cache->buffer_cache); - kprintf(" busy_reading: %lu, %s waiters\n", cache->busy_reading_count, + kprintf(" busy_reading: %" B_PRIu32 ", %s waiters\n", cache->busy_reading_count, cache->busy_reading_waiters ? "has" : "no"); - kprintf(" busy_writing: %lu, %s waiters\n", cache->busy_writing_count, + kprintf(" busy_writing: %" B_PRIu32 ", %s waiters\n", cache->busy_writing_count, cache->busy_writing_waiters ? "has" : "no"); if (!cache->pending_notifications.IsEmpty()) { @@ -2162,7 +2164,7 @@ dump_cache(int argc, char** argv) while (iterator.HasNext()) { cache_notification* notification = iterator.Next(); - kprintf(" %p %5lx %p - %p\n", notification, + kprintf(" %p %5" B_PRIx32 " %p - %p\n", notification, notification->events_pending, notification->hook, notification->data); } @@ -2178,8 +2180,8 @@ dump_cache(int argc, char** argv) cache_transaction* transaction; while ((transaction = (cache_transaction*)hash_next( cache->transaction_hash, &iterator)) != NULL) { - kprintf("%p %5ld %-7s %5ld %5ld %5ld\n", transaction, - transaction->id, transaction->open ? "open" : "closed", + kprintf("%p %5" B_PRId32 " %-7s %5" B_PRId32 " %5" B_PRId32 " %5" B_PRId32 "\n", + transaction, transaction->id, transaction->open ? "open" : "closed", transaction->num_blocks, transaction->main_num_blocks, transaction->sub_num_blocks); } @@ -2211,9 +2213,10 @@ dump_cache(int argc, char** argv) count++; } - kprintf(" %ld blocks total, %ld dirty, %ld discarded, %ld referenced, %ld " - "busy, %" B_PRIu32 " in unused.\n", count, dirty, discarded, referenced, - cache->busy_reading_count, cache->unused_block_count); + kprintf(" %" B_PRIu32 " blocks total, %" B_PRIu32 " dirty, %" B_PRIu32 " discarded" + ", %" B_PRIu32 " referenced, %" B_PRIu32 " busy, %" B_PRIu32 " in unused.\n", + count, dirty, discarded, referenced, cache->busy_reading_count, + cache->unused_block_count); hash_close(cache->hash, &iterator, false); return 0; @@ -2244,20 +2247,20 @@ dump_transaction(int argc, char** argv) int32 id = parse_expression(argv[i + 1]); transaction = lookup_transaction(cache, id); if (transaction == NULL) { - kprintf("No transaction with ID %ld found.\n", id); + kprintf("No transaction with ID %" B_PRId32 " found.\n", id); return 0; } } kprintf("TRANSACTION %p\n", transaction); - kprintf(" id: %ld\n", transaction->id); - kprintf(" num block: %ld\n", transaction->num_blocks); - kprintf(" main num block: %ld\n", transaction->main_num_blocks); - kprintf(" sub num block: %ld\n", transaction->sub_num_blocks); + kprintf(" id: %" B_PRId32 "\n", transaction->id); + kprintf(" num block: %" B_PRId32 "\n", transaction->num_blocks); + kprintf(" main num block: %" B_PRId32 "\n", transaction->main_num_blocks); + kprintf(" sub num block: %" B_PRId32 "\n", transaction->sub_num_blocks); kprintf(" has sub: %d\n", transaction->has_sub_transaction); kprintf(" state: %s\n", transaction->open ? "open" : "closed"); - kprintf(" idle: %Ld secs\n", + kprintf(" idle: %" B_PRId64 " secs\n", (system_time() - transaction->last_used) / 1000000); kprintf(" listeners:\n"); @@ -2266,7 +2269,7 @@ dump_transaction(int argc, char** argv) while (iterator.HasNext()) { cache_listener* listener = iterator.Next(); - kprintf(" %p %5lx %p - %p\n", listener, listener->events_pending, + kprintf(" %p %5" B_PRIx32 " %p - %p\n", listener, listener->events_pending, listener->hook, listener->data); } @@ -2400,7 +2403,7 @@ dump_block_data(int argc, char** argv) if (length > 0 && dump[length - 1] == '\n') length--; - kprintf("%5ld. %.*s\n", index, length, dump); + kprintf("%5" B_PRId32 ". %.*s\n", index, length, dump); if (printStackTrace) { out.Clear(); @@ -2673,7 +2676,7 @@ cache_start_transaction(void* _cache) TransactionLocker locker(cache); if (cache->last_transaction && cache->last_transaction->open) { - panic("last transaction (%ld) still open!\n", + panic("last transaction (%" B_PRId32 ") still open!\n", cache->last_transaction->id); } @@ -2684,7 +2687,7 @@ cache_start_transaction(void* _cache) transaction->id = atomic_add(&cache->next_transaction_id, 1); cache->last_transaction = transaction; - TRACE(("cache_start_transaction(): id %ld started\n", transaction->id)); + TRACE(("cache_start_transaction(): id %" B_PRId32 " started\n", transaction->id)); T(Action("start", cache, transaction)); hash_insert_grow(cache->transaction_hash, transaction); @@ -2699,7 +2702,7 @@ cache_sync_transaction(void* _cache, int32 id) block_cache* cache = (block_cache*)_cache; bool hadBusy; - TRACE(("cache_sync_transaction(id %ld)\n", id)); + TRACE(("cache_sync_transaction(id %" B_PRId32 ")\n", id)); do { TransactionLocker locker(cache); @@ -2754,7 +2757,7 @@ cache_end_transaction(void* _cache, int32 id, block_cache* cache = (block_cache*)_cache; TransactionLocker locker(cache); - TRACE(("cache_end_transaction(id = %ld)\n", id)); + TRACE(("cache_end_transaction(id = %" B_PRId32 ")\n", id)); cache_transaction* transaction = lookup_transaction(cache, id); if (transaction == NULL) { @@ -2830,7 +2833,7 @@ cache_abort_transaction(void* _cache, int32 id) block_cache* cache = (block_cache*)_cache; TransactionLocker locker(cache); - TRACE(("cache_abort_transaction(id = %ld)\n", id)); + TRACE(("cache_abort_transaction(id = %" B_PRId32 ")\n", id)); cache_transaction* transaction = lookup_transaction(cache, id); if (transaction == NULL) { @@ -2849,8 +2852,8 @@ cache_abort_transaction(void* _cache, int32 id) next = block->transaction_next; if (block->original_data != NULL) { - TRACE(("cache_abort_transaction(id = %ld): restored contents of " - "block %Ld\n", transaction->id, block->block_number)); + TRACE(("cache_abort_transaction(id = %" B_PRId32 "): restored contents of " + "block %" B_PRIdOFF "\n", transaction->id, block->block_number)); memcpy(block->current_data, block->original_data, cache->block_size); cache->Free(block->original_data); @@ -2884,7 +2887,7 @@ cache_detach_sub_transaction(void* _cache, int32 id, block_cache* cache = (block_cache*)_cache; TransactionLocker locker(cache); - TRACE(("cache_detach_sub_transaction(id = %ld)\n", id)); + TRACE(("cache_detach_sub_transaction(id = %" B_PRId32 ")\n", id)); cache_transaction* transaction = lookup_transaction(cache, id); if (transaction == NULL) { @@ -2995,7 +2998,7 @@ cache_abort_sub_transaction(void* _cache, int32 id) block_cache* cache = (block_cache*)_cache; TransactionLocker locker(cache); - TRACE(("cache_abort_sub_transaction(id = %ld)\n", id)); + TRACE(("cache_abort_sub_transaction(id = %" B_PRId32 ")\n", id)); cache_transaction* transaction = lookup_transaction(cache, id); if (transaction == NULL) { @@ -3023,8 +3026,8 @@ cache_abort_sub_transaction(void* _cache, int32 id) cache->block_size); } else if (block->parent_data != block->current_data) { // the block has been changed and must be restored - TRACE(("cache_abort_sub_transaction(id = %ld): restored contents " - "of block %Ld\n", transaction->id, block->block_number)); + TRACE(("cache_abort_sub_transaction(id = %" B_PRId32 "): restored contents " + "of block %" B_PRIdOFF "\n", transaction->id, block->block_number)); memcpy(block->current_data, block->parent_data, cache->block_size); cache->Free(block->parent_data); } @@ -3047,11 +3050,11 @@ cache_start_sub_transaction(void* _cache, int32 id) block_cache* cache = (block_cache*)_cache; TransactionLocker locker(cache); - TRACE(("cache_start_sub_transaction(id = %ld)\n", id)); + TRACE(("cache_start_sub_transaction(id = %" B_PRId32 ")\n", id)); cache_transaction* transaction = lookup_transaction(cache, id); if (transaction == NULL) { - panic("cache_start_sub_transaction(): invalid transaction ID %ld\n", + panic("cache_start_sub_transaction(): invalid transaction ID %" B_PRId32 "\n", id); return B_BAD_VALUE; } @@ -3353,7 +3356,7 @@ block_cache_sync_etc(void* _cache, off_t blockNumber, size_t numBlocks) // transaction or no transaction only if (blockNumber < 0 || blockNumber >= cache->max_blocks) { - panic("block_cache_sync_etc: invalid block number %Ld (max %Ld)", + panic("block_cache_sync_etc: invalid block number %" B_PRIdOFF " (max %" B_PRIdOFF ")", blockNumber, cache->max_blocks - 1); return B_BAD_VALUE; } @@ -3424,7 +3427,7 @@ block_cache_discard(void* _cache, off_t blockNumber, size_t numBlocks) } else { if (block->transaction != NULL && block->parent_data != NULL && block->parent_data != block->current_data) { - panic("Discarded block %Ld has already been changed in this " + panic("Discarded block %" B_PRIdOFF " has already been changed in this " "transaction!", blockNumber); } @@ -3465,7 +3468,7 @@ block_cache_get_writable_etc(void* _cache, off_t blockNumber, off_t base, block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); - TRACE(("block_cache_get_writable_etc(block = %Ld, transaction = %ld)\n", + TRACE(("block_cache_get_writable_etc(block = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n", blockNumber, transaction)); if (cache->read_only) panic("tried to get writable block on a read-only cache!"); @@ -3489,7 +3492,7 @@ block_cache_get_empty(void* _cache, off_t blockNumber, int32 transaction) block_cache* cache = (block_cache*)_cache; MutexLocker locker(&cache->lock); - TRACE(("block_cache_get_empty(block = %Ld, transaction = %ld)\n", + TRACE(("block_cache_get_empty(block = %" B_PRIdOFF ", transaction = %" B_PRId32 ")\n", blockNumber, transaction)); if (cache->read_only) panic("tried to get empty writable block on a read-only cache!"); diff --git a/src/system/kernel/cache/file_cache.cpp b/src/system/kernel/cache/file_cache.cpp index 2825ef1a60..01257d792b 100644 --- a/src/system/kernel/cache/file_cache.cpp +++ b/src/system/kernel/cache/file_cache.cpp @@ -555,7 +555,7 @@ write_to_cache(file_cache_ref* ref, void* cookie, off_t offset, generic_addr_t last = vecs[vecCount - 1].base + vecs[vecCount - 1].length - B_PAGE_SIZE; - if (offset + pageOffset + bufferSize == ref->cache->virtual_end) { + if ((off_t)(offset + pageOffset + bufferSize) == ref->cache->virtual_end) { // the space in the page after this write action needs to be cleaned vm_memset_physical(last + lastPageOffset, 0, B_PAGE_SIZE - lastPageOffset); @@ -724,7 +724,7 @@ cache_io(void* _cacheRef, void* cookie, off_t offset, addr_t buffer, size_t size = *_size; offset -= pageOffset; - if (offset + pageOffset + size > fileSize) { + if ((off_t)(offset + pageOffset + size) > fileSize) { // adapt size to be within the file's offsets size = fileSize - pageOffset - offset; *_size = size; @@ -951,7 +951,7 @@ cache_prefetch_vnode(struct vnode* vnode, off_t offset, size_t size) file_cache_ref* ref = ((VMVnodeCache*)cache)->FileCacheRef(); off_t fileSize = cache->virtual_end; - if (offset + size > fileSize) + if ((off_t)(offset + size) > fileSize) size = fileSize - offset; // "offset" and "size" are always aligned to B_PAGE_SIZE, @@ -1088,7 +1088,7 @@ file_cache_init_post_boot_device(void) if (get_module("file_cache/launch_speedup/v1", (module_info**)&sCacheModule) == B_OK) { - dprintf("** opened launch speedup: %Ld\n", system_time()); + dprintf("** opened launch speedup: %" B_PRId64 "\n", system_time()); } return B_OK; } diff --git a/src/system/kernel/cache/file_map.cpp b/src/system/kernel/cache/file_map.cpp index d9e0ddca01..931bc0f516 100644 --- a/src/system/kernel/cache/file_map.cpp +++ b/src/system/kernel/cache/file_map.cpp @@ -412,10 +412,10 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count, *_count = 0; return B_OK; } - if (offset + size > fSize) { + if ((off_t)(offset + size) > fSize) { if (align > 1) { off_t alignedSize = (fSize + align - 1) & ~(off_t)(align - 1); - if (offset + size >= alignedSize) + if ((off_t)(offset + size) >= alignedSize) padLastVec = alignedSize - fSize; } size = fSize - offset; @@ -441,7 +441,7 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count, vecs[0].offset = -1; vecs[0].length = fileExtent->disk.length - offset; - if (vecs[0].length >= size) { + if (vecs[0].length >= (off_t)size) { vecs[0].length = size + padLastVec; *_count = 1; return B_OK; @@ -457,7 +457,7 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count, vecs[vecIndex++] = fileExtent->disk; - if (size <= fileExtent->disk.length) { + if ((off_t)size <= fileExtent->disk.length) { vecs[vecIndex - 1].length = size + padLastVec; break; } @@ -499,7 +499,7 @@ dump_file_map(int argc, char** argv) } kprintf("FileMap %p\n", map); - kprintf(" size %Ld\n", map->Size()); + kprintf(" size %" B_PRIdOFF "\n", map->Size()); kprintf(" count %lu\n", map->Count()); if (!printExtents) @@ -508,8 +508,9 @@ dump_file_map(int argc, char** argv) for (uint32 i = 0; i < map->Count(); i++) { file_extent* extent = map->ExtentAt(i); - kprintf(" [%lu] offset %Ld, disk offset %Ld, length %Ld\n", - i, extent->offset, extent->disk.offset, extent->disk.length); + kprintf(" [%" B_PRIu32 "] offset %" B_PRIdOFF ", disk offset %" + B_PRIdOFF ", length %" B_PRIdOFF "\n", i, extent->offset, + extent->disk.offset, extent->disk.length); } return 0; @@ -555,9 +556,10 @@ dump_file_map_stats(int argc, char** argv) count++; } - kprintf("%ld file maps (%ld empty), %Ld file bytes in total, %Ld bytes " - "cached, %lu extents\n", count, emptyCount, size, mapSize, extents); - kprintf("average %lu extents per map for %Ld bytes.\n", + kprintf("%" B_PRId32 " file maps (%" B_PRIu32 " empty), %" B_PRIdOFF " file" + " bytes in total, %" B_PRIdOFF " bytes cached, %" B_PRIu32 " extents\n", + count, emptyCount, size, mapSize, extents); + kprintf("average %" B_PRIu32 " extents per map for %" B_PRIdOFF " bytes.\n", extents / (count - emptyCount), mapSize / (count - emptyCount)); return 0; diff --git a/src/system/kernel/condition_variable.cpp b/src/system/kernel/condition_variable.cpp index ef0dcd28d0..47215606b1 100644 --- a/src/system/kernel/condition_variable.cpp +++ b/src/system/kernel/condition_variable.cpp @@ -315,7 +315,7 @@ ConditionVariable::Dump() const for (EntryList::ConstIterator it = fEntries.GetIterator(); ConditionVariableEntry* entry = it.Next();) { - kprintf(" %ld", entry->fThread->id); + kprintf(" %" B_PRId32, entry->fThread->id); } kprintf("\n"); } @@ -330,7 +330,7 @@ ConditionVariable::_Notify(bool all, bool schedulerLocked, status_t result) if (!fEntries.IsEmpty()) { if (result > B_OK) { - panic("tried to notify with invalid result %ld\n", result); + panic("tried to notify with invalid result %" B_PRId32 "\n", result); result = B_ERROR; } diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index ad3c291ce2..64dd51aec4 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -9,6 +9,8 @@ /*! Contains the ELF loader */ +#ifndef __x86_64__ + #include #include @@ -2587,3 +2589,4 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, return B_OK; } +#endif \ No newline at end of file diff --git a/src/system/kernel/heap.cpp b/src/system/kernel/heap.cpp index 38c4dea880..a2815bff6a 100644 --- a/src/system/kernel/heap.cpp +++ b/src/system/kernel/heap.cpp @@ -313,8 +313,9 @@ dump_page(heap_page *page) count++; kprintf("\t\tpage %p: bin_index: %u; free_count: %u; empty_index: %u; " - "free_list %p (%lu entr%s)\n", page, page->bin_index, page->free_count, - page->empty_index, page->free_list, count, count == 1 ? "y" : "ies"); + "free_list %p (%" B_PRIu32 " entr%s)\n", page, page->bin_index, + page->free_count, page->empty_index, page->free_list, count, + count == 1 ? "y" : "ies"); } @@ -325,8 +326,9 @@ dump_bin(heap_bin *bin) for (heap_page *page = bin->page_list; page != NULL; page = page->next) count++; - kprintf("\telement_size: %lu; max_free_count: %u; page_list %p (%lu pages" - ");\n", bin->element_size, bin->max_free_count, bin->page_list, count); + kprintf("\telement_size: %" B_PRIu32 "; max_free_count: %u; page_list %p " + "(%" B_PRIu32 " pages);\n", bin->element_size, bin->max_free_count, + bin->page_list, count); for (heap_page *page = bin->page_list; page != NULL; page = page->next) dump_page(page); @@ -347,10 +349,11 @@ dump_allocator_areas(heap_allocator *heap) { heap_area *area = heap->all_areas; while (area) { - kprintf("\tarea %p: area: %ld; base: 0x%08lx; size: %lu; page_count: " - "%lu; free_pages: %p (%lu entr%s)\n", area, area->area, area->base, - area->size, area->page_count, area->free_pages, - area->free_page_count, area->free_page_count == 1 ? "y" : "ies"); + kprintf("\tarea %p: area: %" B_PRId32 "; base: %p; size: %zu; page_count: " + "%" B_PRIu32 "; free_pages: %p (%" B_PRIu32 " entr%s)\n", area, + area->area, (void *)area->base, area->size, area->page_count, + area->free_pages, area->free_page_count, + area->free_page_count == 1 ? "y" : "ies"); area = area->all_next; } @@ -361,10 +364,11 @@ dump_allocator_areas(heap_allocator *heap) static void dump_allocator(heap_allocator *heap, bool areas, bool bins) { - kprintf("allocator %p: name: %s; page_size: %lu; bin_count: %lu; pages: " - "%lu; free_pages: %lu; empty_areas: %lu\n", heap, heap->name, - heap->page_size, heap->bin_count, heap->total_pages, - heap->total_free_pages, heap->empty_areas); + kprintf("allocator %p: name: %s; page_size: %" B_PRIu32 "; bin_count: " + "%" B_PRIu32 "; pages: %" B_PRIu32 "; free_pages: %" B_PRIu32 "; " + "empty_areas: %" B_PRIu32 "\n", heap, heap->name, heap->page_size, + heap->bin_count, heap->total_pages, heap->total_free_pages, + heap->empty_areas); if (areas) dump_allocator_areas(heap); @@ -481,8 +485,8 @@ dump_allocations(int argc, char **argv) continue; if (!statsOnly) { - kprintf("address: 0x%08lx; size: %lu bytes\n", - base, elementSize); + kprintf("address: 0x%p; size: %lu bytes\n", + (void *)base, elementSize); } totalSize += elementSize; @@ -502,7 +506,7 @@ dump_allocations(int argc, char **argv) size_t size = pageCount * heap->page_size; if (!statsOnly) { - kprintf("address: 0x%08lx; size: %lu bytes\n", base, + kprintf("address: %p; size: %lu bytes\n", (void *)base, size); } @@ -521,7 +525,7 @@ dump_allocations(int argc, char **argv) break; } - kprintf("total allocations: %lu; total bytes: %lu\n", totalCount, totalSize); + kprintf("total allocations: %" B_PRIu32 "; total bytes: %zu\n", totalCount, totalSize); return 0; } @@ -1096,9 +1100,9 @@ heap_add_area(heap_allocator *heap, area_id areaID, addr_t base, size_t size) pageLocker.Unlock(); areaWriteLocker.Unlock(); - dprintf("heap_add_area: area %ld added to %s heap %p - usable range 0x%08lx " - "- 0x%08lx\n", area->area, heap->name, heap, area->base, - area->base + area->size); + dprintf("heap_add_area: area %" B_PRId32 " added to %s heap %p - usable " + "range %p - %p\n", area->area, heap->name, heap, (void *)area->base, + (void *)(area->base + area->size)); } @@ -1142,9 +1146,9 @@ heap_remove_area(heap_allocator *heap, heap_area *area) heap->total_pages -= area->page_count; heap->total_free_pages -= area->free_page_count; - dprintf("heap_remove_area: area %ld with range 0x%08lx - 0x%08lx removed " - "from %s heap %p\n", area->area, area->base, area->base + area->size, - heap->name, heap); + dprintf("heap_remove_area: area %" B_PRId32 " with range %p - %p removed " + "from %s heap %p\n", area->area, (void *)area->base, + (void *)(area->base + area->size), heap->name, heap); return B_OK; } @@ -1659,7 +1663,7 @@ heap_free(heap_allocator *heap, void *address) if (((addr_t)address - area->base - page->index * heap->page_size) % bin->element_size != 0) { panic("free(): passed invalid pointer %p supposed to be in bin for " - "element size %ld\n", address, bin->element_size); + "element size %" B_PRIu32 "\n", address, bin->element_size); return B_ERROR; } diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp index 05bd513f06..787124db81 100644 --- a/src/system/kernel/image.cpp +++ b/src/system/kernel/image.cpp @@ -254,21 +254,22 @@ dump_images_list(int argc, char **argv) team_id id = strtol(argv[1], NULL, 0); team = team_get_team_struct_locked(id); if (team == NULL) { - kprintf("No team with ID %ld found\n", id); + kprintf("No team with ID %" B_PRId32 " found\n", id); return 1; } } else team = thread_get_current_thread()->team; - kprintf("Registered images of team %ld\n", team->id); + kprintf("Registered images of team %" B_PRId32 "\n", team->id); kprintf(" ID text size data size name\n"); while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { image_info *info = &image->info; - kprintf("%6ld %p %-7ld %p %-7ld %s\n", info->id, info->text, info->text_size, - info->data, info->data_size, info->name); + kprintf("%6" B_PRId32 " %p %-7" B_PRId32 " %p %-7" B_PRId32 " %s\n", + info->id, info->text, info->text_size, info->data, info->data_size, + info->name); } return 0; @@ -417,8 +418,8 @@ _user_image_relocated(image_id id) // get an image info error = _get_image_info(id, &info, sizeof(image_info)); if (error != B_OK) { - dprintf("_user_image_relocated(%ld): Failed to get image info: %lx\n", - id, error); + dprintf("_user_image_relocated(%" B_PRId32 "): Failed to get image " + "info: %" B_PRIx32 "\n", id, error); return; } diff --git a/src/system/kernel/int.cpp b/src/system/kernel/int.cpp index d30b320cf2..59c9671814 100644 --- a/src/system/kernel/int.cpp +++ b/src/system/kernel/int.cpp @@ -80,7 +80,7 @@ dump_int_statistics(int argc, char **argv) && sVectors[i].handler_list == NULL) continue; - kprintf("int %3d, enabled %ld, handled %8lld, unhandled %8lld%s%s\n", + kprintf("int %3d, enabled %" B_PRId32 ", handled %8lld, unhandled %8lld%s%s\n", i, sVectors[i].enable_count, sVectors[i].handled_count, sVectors[i].unhandled_count, B_SPINLOCK_IS_LOCKED(&sVectors[i].vector_lock) ? ", ACTIVE" : "", diff --git a/src/system/kernel/low_resource_manager.cpp b/src/system/kernel/low_resource_manager.cpp index d64b675d71..55962db93d 100644 --- a/src/system/kernel/low_resource_manager.cpp +++ b/src/system/kernel/low_resource_manager.cpp @@ -59,9 +59,9 @@ static off_t sWarnMemoryLimit; static off_t sCriticalMemoryLimit; // address space limits -static const off_t kMinNoteSpaceLimit = 128 * 1024 * 1024; -static const off_t kMinWarnSpaceLimit = 64 * 1024 * 1024; -static const off_t kMinCriticalSpaceLimit = 32 * 1024 * 1024; +static const size_t kMinNoteSpaceLimit = 128 * 1024 * 1024; +static const size_t kMinWarnSpaceLimit = 64 * 1024 * 1024; +static const size_t kMinCriticalSpaceLimit = 32 * 1024 * 1024; static int32 sLowPagesState = B_NO_LOW_RESOURCE; @@ -310,8 +310,8 @@ dump_handlers(int argc, char** argv) handler->resources & B_KERNEL_RESOURCE_SEMAPHORES ? 's' : ' ', handler->resources & B_KERNEL_RESOURCE_ADDRESS_SPACE ? 'a' : ' '); - kprintf("%p %p %s %4ld %s\n", handler->function, handler->data, - resources, handler->priority, symbol); + kprintf("%p %p %s %4" B_PRId32 " %s\n", handler->function, + handler->data, resources, handler->priority, symbol); } return 0; diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp index a5797d8940..6ce9648e39 100644 --- a/src/system/kernel/main.cpp +++ b/src/system/kernel/main.cpp @@ -361,7 +361,7 @@ main2(void *unused) resume_thread(thread); TRACE("Bootscript started\n"); } else - dprintf("error starting \"%s\" error = %ld \n", args[0], thread); + dprintf("error starting \"%s\" error = %" B_PRId32 " \n", args[0], thread); } return 0; diff --git a/src/system/kernel/module.cpp b/src/system/kernel/module.cpp index 0c0be15553..202fb7c239 100644 --- a/src/system/kernel/module.cpp +++ b/src/system/kernel/module.cpp @@ -457,7 +457,7 @@ unload_module_image(module_image* moduleImage, bool remove) ASSERT_LOCKED_RECURSIVE(&sModulesLock); if (moduleImage->ref_count != 0) { - FATAL(("Can't unload %s due to ref_cnt = %ld\n", moduleImage->path, + FATAL(("Can't unload %s due to ref_cnt = %" B_PRId32 "\n", moduleImage->path, moduleImage->ref_count)); return B_ERROR; } @@ -1172,8 +1172,8 @@ dump_modules(int argc, char** argv) while ((module = (struct module*)hash_next(sModulesHash, &iterator)) != NULL) { - kprintf("%p: \"%s\", \"%s\" (%ld), refcount = %ld, state = %d, " - "mimage = %p\n", module, module->name, + kprintf("%p: \"%s\", \"%s\" (%" B_PRId32 "), refcount = %" B_PRId32 ", " + "state = %d, mimage = %p\n", module, module->name, module->module_image ? module->module_image->path : "", module->offset, module->ref_count, module->state, module->module_image); @@ -1184,8 +1184,9 @@ dump_modules(int argc, char** argv) while ((image = (struct module_image*)hash_next(sModuleImagesHash, &iterator)) != NULL) { - kprintf("%p: \"%s\" (image_id = %ld), info = %p, refcount = %ld\n", - image, image->path, image->image, image->info, image->ref_count); + kprintf("%p: \"%s\" (image_id = %" B_PRId32 "), info = %p, refcount = " + "%" B_PRId32 "\n", image, image->path, image->image, image->info, + image->ref_count); } return 0; } diff --git a/src/system/kernel/port.cpp b/src/system/kernel/port.cpp index fd66ec22af..26fb39d1e3 100644 --- a/src/system/kernel/port.cpp +++ b/src/system/kernel/port.cpp @@ -403,8 +403,9 @@ dump_port_list(int argc, char** argv) || (name != NULL && strstr(port->lock.name, name) == NULL)) continue; - kprintf("%p %8ld %4ld %9ld %9ld %8ld %6ld %s\n", port, - port->id, port->capacity, port->read_count, port->write_count, + kprintf("%p %8" B_PRId32 " %4" B_PRId32 " %9" B_PRIu32 " %9" B_PRId32 + " %8" B_PRId32 " %6" B_PRId32 " %s\n", port, port->id, + port->capacity, port->read_count, port->write_count, port->total_count, port->owner, port->lock.name); } @@ -416,20 +417,20 @@ static void _dump_port_info(Port* port) { kprintf("PORT: %p\n", port); - kprintf(" id: %ld\n", port->id); + kprintf(" id: %" B_PRId32 "\n", port->id); kprintf(" name: \"%s\"\n", port->lock.name); - kprintf(" owner: %ld\n", port->owner); - kprintf(" capacity: %ld\n", port->capacity); - kprintf(" read_count: %ld\n", port->read_count); - kprintf(" write_count: %ld\n", port->write_count); - kprintf(" total count: %ld\n", port->total_count); + kprintf(" owner: %" B_PRId32 "\n", port->owner); + kprintf(" capacity: %" B_PRId32 "\n", port->capacity); + kprintf(" read_count: %" B_PRIu32 "\n", port->read_count); + kprintf(" write_count: %" B_PRId32 "\n", port->write_count); + kprintf(" total count: %" B_PRId32 "\n", port->total_count); if (!port->messages.IsEmpty()) { kprintf("messages:\n"); MessageList::Iterator iterator = port->messages.GetIterator(); while (port_message* message = iterator.Next()) { - kprintf(" %p %08lx %ld\n", message, message->code, message->size); + kprintf(" %p %08" B_PRIx32 " %ld\n", message, message->code, message->size); } } @@ -463,7 +464,8 @@ dump_port_info(int argc, char** argv) int32 num = parse_expression(argv[1]); Port* port = sPorts.Lookup(num); if (port == NULL) { - kprintf("port %ld (%#lx) doesn't exist!\n", num, num); + kprintf("port %" B_PRId32 " (%#" B_PRIx32 ") doesn't exist!\n", + num, num); return 0; } _dump_port_info(port); @@ -1180,7 +1182,7 @@ _get_port_message_info_etc(port_id id, port_message_info* info, // determine tail & get the length of the message port_message* message = port->messages.Head(); if (message == NULL) { - panic("port %ld: no messages found\n", port->id); + panic("port %" B_PRId32 ": no messages found\n", port->id); return B_ERROR; } @@ -1289,7 +1291,7 @@ read_port_etc(port_id id, int32* _code, void* buffer, size_t bufferSize, // determine tail & get the length of the message port_message* message = port->messages.Head(); if (message == NULL) { - panic("port %ld: no messages found\n", port->id); + panic("port %" B_PRId32 ": no messages found\n", port->id); return B_ERROR; } diff --git a/src/system/kernel/real_time_clock.cpp b/src/system/kernel/real_time_clock.cpp index 6f99492af8..b73c8f920f 100644 --- a/src/system/kernel/real_time_clock.cpp +++ b/src/system/kernel/real_time_clock.cpp @@ -86,7 +86,7 @@ rtc_debug(int argc, char **argv) currentTime = (systemTimeOffset + system_time()) / 1000000; dprintf("system_time: %Ld\n", system_time()); dprintf("system_time_offset: %Ld\n", systemTimeOffset); - dprintf("current_time: %lu\n", currentTime); + dprintf("current_time: %" B_PRIu32 "\n", currentTime); } else { // If there was an argument, reset the system and hw time. set_real_time_clock(strtoul(argv[1], NULL, 10)); diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index ad32ddd349..5a5a20af43 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -163,8 +163,8 @@ dump_sem_list(int argc, char** argv) || (owner != -1 && sem->u.used.owner != owner)) continue; - kprintf("%p %6ld %5ld %6ld " - "%6ld " + kprintf("%p %6" B_PRId32 " %5" B_PRId32 " %6" B_PRId32 " " + "%6" B_PRId32 " " " %s\n", sem, sem->id, sem->u.used.count, sem->u.used.owner, sem->u.used.last_acquirer > 0 ? sem->u.used.last_acquirer : 0, @@ -179,16 +179,16 @@ static void dump_sem(struct sem_entry* sem) { kprintf("SEM: %p\n", sem); - kprintf("id: %ld (%#lx)\n", sem->id, sem->id); + kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", sem->id, sem->id); if (sem->id >= 0) { kprintf("name: '%s'\n", sem->u.used.name); - kprintf("owner: %ld\n", sem->u.used.owner); - kprintf("count: %ld\n", sem->u.used.count); + kprintf("owner: %" B_PRId32 "\n", sem->u.used.owner); + kprintf("count: %" B_PRId32 "\n", sem->u.used.count); kprintf("queue: "); if (!sem->queue.IsEmpty()) { ThreadQueue::Iterator it = sem->queue.GetIterator(); while (queued_thread* entry = it.Next()) - kprintf(" %ld", entry->thread->id); + kprintf(" %" B_PRId32, entry->thread->id); kprintf("\n"); } else kprintf(" -\n"); @@ -198,9 +198,9 @@ dump_sem(struct sem_entry* sem) set_debug_variable("_owner", sem->u.used.owner); #if DEBUG_SEM_LAST_ACQUIRER - kprintf("last acquired by: %ld, count: %ld\n", + kprintf("last acquired by: %" B_PRId32 ", count: %" B_PRId32 "\n", sem->u.used.last_acquirer, sem->u.used.last_acquire_count); - kprintf("last released by: %ld, count: %ld\n", + kprintf("last released by: %" B_PRId32 ", count: %" B_PRId32 "\n", sem->u.used.last_releaser, sem->u.used.last_release_count); if (sem->u.used.last_releaser != 0) @@ -217,7 +217,7 @@ dump_sem(struct sem_entry* sem) unset_debug_variable("_acquirer"); } else { kprintf("next: %p\n", sem->u.unused.next); - kprintf("next_id: %ld\n", sem->u.unused.next_id); + kprintf("next_id: %" B_PRId32 "\n", sem->u.unused.next_id); } } @@ -378,8 +378,8 @@ delete_sem_internal(sem_id id, bool checkPermission) RELEASE_SEM_LOCK(sSems[slot]); RELEASE_SEM_LIST_LOCK(); restore_interrupts(state); - dprintf("thread %ld tried to delete kernel semaphore %ld.\n", - thread_get_current_thread_id(), id); + dprintf("thread %" B_PRId32 " tried to delete kernel semaphore " + "%" B_PRId32 ".\n", thread_get_current_thread_id(), id); return B_NOT_ALLOWED; } @@ -387,7 +387,7 @@ delete_sem_internal(sem_id id, bool checkPermission) list_remove_link(&sSems[slot].u.used.team_link); sSems[slot].u.used.owner = -1; } else - panic("sem %ld has no owner", id); + panic("sem %" B_PRId32 " has no owner", id); RELEASE_SEM_LIST_LOCK(); @@ -769,8 +769,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, return B_NO_MORE_SEMS; if (!are_interrupts_enabled()) { - panic("switch_sem_etc: called with interrupts disabled for sem %ld\n", - id); + panic("switch_sem_etc: called with interrupts disabled for sem " + "%" B_PRId32 "\n", id); } if (id < 0) @@ -793,8 +793,8 @@ switch_sem_etc(sem_id semToBeReleased, sem_id id, int32 count, // doesn't have any use outside the kernel if ((flags & B_CHECK_PERMISSION) != 0 && sSems[slot].u.used.owner == team_get_kernel_team_id()) { - dprintf("thread %ld tried to acquire kernel semaphore %ld.\n", - thread_get_current_thread_id(), id); + dprintf("thread %" B_PRId32 " tried to acquire kernel semaphore " + "%" B_PRId32 ".\n", thread_get_current_thread_id(), id); status = B_NOT_ALLOWED; goto err; } @@ -945,7 +945,7 @@ release_sem_etc(sem_id id, int32 count, uint32 flags) // doesn't have any use outside the kernel if ((flags & B_CHECK_PERMISSION) != 0 && sSems[slot].u.used.owner == team_get_kernel_team_id()) { - dprintf("thread %ld tried to release kernel semaphore.\n", + dprintf("thread %" B_PRId32 " tried to release kernel semaphore.\n", thread_get_current_thread_id()); return B_NOT_ALLOWED; } diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 899d81c259..7c4a6b963f 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -234,10 +234,10 @@ dump_ici_messages(int argc, char** argv) message = message->next; } - kprintf("ICI broadcast messages: %ld, first: %p\n", count, + kprintf("ICI broadcast messages: %" B_PRId32 ", first: %p\n", count, sBroadcastMessages); - kprintf(" done: %ld\n", doneCount); - kprintf(" unreferenced: %ld\n", unreferencedCount); + kprintf(" done: %" B_PRId32 "\n", doneCount); + kprintf(" unreferenced: %" B_PRId32 "\n", unreferencedCount); // count per-CPU messages for (int32 i = 0; i < sNumCPUs; i++) { @@ -248,8 +248,8 @@ dump_ici_messages(int argc, char** argv) message = message->next; } - kprintf("CPU %ld messages: %ld, first: %p\n", i, count, - sCPUMessages[i]); + kprintf("CPU %" B_PRId32 " messages: %" B_PRId32 ", first: %p\n", i, + count, sCPUMessages[i]); } return 0; @@ -271,15 +271,15 @@ dump_ici_message(int argc, char** argv) smp_msg* message = (smp_msg*)(addr_t)address; kprintf("ICI message %p:\n", message); kprintf(" next: %p\n", message->next); - kprintf(" message: %ld\n", message->message); - kprintf(" data: %ld\n", message->data); - kprintf(" data2: %ld\n", message->data2); - kprintf(" data3: %ld\n", message->data3); + kprintf(" message: %" B_PRId32 "\n", message->message); + kprintf(" data: %" B_PRIu32 "\n", message->data); + kprintf(" data2: %" B_PRIu32 "\n", message->data2); + kprintf(" data3: %" B_PRIu32 "\n", message->data3); kprintf(" data_ptr: %p\n", message->data_ptr); - kprintf(" flags: %lx\n", message->flags); - kprintf(" ref_count: %lx\n", message->ref_count); + kprintf(" flags: %" B_PRIx32 "\n", message->flags); + kprintf(" ref_count: %" B_PRIx32 "\n", message->ref_count); kprintf(" done: %s\n", message->done ? "true" : "false"); - kprintf(" proc_bitmap: %lx\n", message->proc_bitmap); + kprintf(" proc_bitmap: %" B_PRIx32 "\n", message->proc_bitmap); return 0; } @@ -361,7 +361,7 @@ acquire_spinlock(spinlock* lock) oldValue = atomic_or((int32*)lock, 1); if (oldValue != 0) { panic("acquire_spinlock: attempt to acquire lock %p twice on " - "non-SMP system (last caller: %p, value %ld)", lock, + "non-SMP system (last caller: %p, value %" B_PRId32 ")", lock, find_lock_caller(lock), oldValue); } @@ -458,7 +458,7 @@ acquire_spinlock_cpu(int32 currentCPU, spinlock *lock) oldValue = atomic_or((int32*)lock, 1); if (oldValue != 0) { panic("acquire_spinlock_cpu(): attempt to acquire lock %p twice on " - "non-SMP system (last caller: %p, value %ld)", lock, + "non-SMP system (last caller: %p, value %" B_PRId32 ")", lock, find_lock_caller(lock), oldValue); } @@ -755,8 +755,8 @@ process_pending_ici(int32 currentCPU) } default: - dprintf("smp_intercpu_int_handler: got unknown message %ld\n", - msg->message); + dprintf("smp_intercpu_int_handler: got unknown message %" B_PRId32 + "\n", msg->message); break; } diff --git a/src/system/kernel/system_info.cpp b/src/system/kernel/system_info.cpp index 0315c0d7ea..a97cdcad10 100644 --- a/src/system/kernel/system_info.cpp +++ b/src/system/kernel/system_info.cpp @@ -50,20 +50,23 @@ dump_info(int argc, char **argv) __VERSION__); kprintf("revision: %s\n\n", get_haiku_revision()); - kprintf("cpu count: %ld, active times:\n", smp_get_num_cpus()); + kprintf("cpu count: %" B_PRId32 ", active times:\n", smp_get_num_cpus()); for (int32 i = 0; i < smp_get_num_cpus(); i++) - kprintf(" [%ld] %Ld\n", i + 1, gCPU[i].active_time); + kprintf(" [%" B_PRId32 "] %" B_PRId64 "\n", i + 1, gCPU[i].active_time); // ToDo: Add page_faults kprintf("pages:\t\t%" B_PRIuPHYSADDR " (%" B_PRIuPHYSADDR " max)\n", vm_page_num_pages() - vm_page_num_free_pages(), vm_page_num_pages()); - kprintf("sems:\t\t%ld (%ld max)\n", sem_used_sems(), sem_max_sems()); - kprintf("ports:\t\t%ld (%ld max)\n", port_used_ports(), port_max_ports()); - kprintf("threads:\t%ld (%ld max)\n", thread_used_threads(), - thread_max_threads()); - kprintf("teams:\t\t%ld (%ld max)\n", team_used_teams(), team_max_teams()); + kprintf("sems:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", sem_used_sems(), + sem_max_sems()); + kprintf("ports:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", port_used_ports(), + port_max_ports()); + kprintf("threads:\t%" B_PRId32 " (%" B_PRId32 " max)\n", + thread_used_threads(), thread_max_threads()); + kprintf("teams:\t\t%" B_PRId32 " (%" B_PRId32 " max)\n", team_used_teams(), + team_max_teams()); return 0; } From f76bc433e1582f4f5424cd5c95613cb247e15a98 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 13 Jun 2012 17:45:22 +0100 Subject: [PATCH 006/273] Added some x86_64 system/kernel headers and kernel Jamfiles. * Not all of these headers are correct yet, just adding what's necessary to get things to compile for the time being. --- headers/os/arch/x86_64/arch_debugger.h | 71 ++++++++ headers/os/kernel/debugger.h | 5 +- headers/private/kernel/arch/x86_64/arch_cpu.h | 6 +- .../private/kernel/arch/x86_64/arch_debug.h | 17 ++ headers/private/kernel/arch/x86_64/arch_int.h | 80 ++++++++- .../private/kernel/arch/x86_64/arch_kernel.h | 6 +- .../kernel/arch/x86_64/arch_kernel_args.h | 6 +- .../kernel/arch/x86_64/arch_system_info.h | 28 ++- .../private/kernel/arch/x86_64/arch_thread.h | 34 +++- .../kernel/arch/x86_64/arch_thread_types.h | 34 +++- .../kernel/arch/x86_64/arch_user_debugger.h | 6 +- headers/private/kernel/arch/x86_64/arch_vm.h | 16 ++ .../arch/x86_64/arch_vm_translation_map.h | 9 + .../kernel/arch/x86_64/arch_vm_types.h | 9 + .../system/arch/x86_64/arch_commpage_defs.h | 15 ++ .../system/arch/x86_64/arch_real_time_data.h | 17 ++ src/system/kernel/arch/x86_64/Jamfile | 21 +++ src/system/kernel/arch/x86_64/arch_cpu.cpp | 164 ++++++++++++++++++ src/system/kernel/arch/x86_64/asm_offsets.cpp | 88 ++++++++++ src/system/kernel/lib/arch/x86_64/Jamfile | 30 ++++ .../kernel/lib/arch/x86_64/arch_string.cpp | 36 ++++ 21 files changed, 669 insertions(+), 29 deletions(-) create mode 100644 headers/os/arch/x86_64/arch_debugger.h create mode 100644 headers/private/kernel/arch/x86_64/arch_debug.h create mode 100644 headers/private/kernel/arch/x86_64/arch_vm.h create mode 100644 headers/private/kernel/arch/x86_64/arch_vm_translation_map.h create mode 100644 headers/private/kernel/arch/x86_64/arch_vm_types.h create mode 100644 headers/private/system/arch/x86_64/arch_commpage_defs.h create mode 100644 headers/private/system/arch/x86_64/arch_real_time_data.h create mode 100644 src/system/kernel/arch/x86_64/Jamfile create mode 100644 src/system/kernel/arch/x86_64/arch_cpu.cpp create mode 100644 src/system/kernel/arch/x86_64/asm_offsets.cpp create mode 100644 src/system/kernel/lib/arch/x86_64/Jamfile create mode 100644 src/system/kernel/lib/arch/x86_64/arch_string.cpp diff --git a/headers/os/arch/x86_64/arch_debugger.h b/headers/os/arch/x86_64/arch_debugger.h new file mode 100644 index 0000000000..5b9220b340 --- /dev/null +++ b/headers/os/arch/x86_64/arch_debugger.h @@ -0,0 +1,71 @@ +/* + * Copyright 2005-2012, Haiku Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _ARCH_X86_64_DEBUGGER_H +#define _ARCH_X86_64_DEBUGGER_H + + +typedef struct x86_64_fp_register { + uint8 value[10]; + uint8 reserved[6]; +} x86_64_fp_register; + + +typedef struct x86_64_xmm_register { + uint8 value[16]; +} x86_64_xmm_register; + + +typedef struct x86_64_extended_registers { + uint16 control; + uint16 status; + uint8 tag; + uint8 reserved1; + uint16 opcode; + uint64 instruction_pointer; + uint64 data_pointer; + uint32 mxcsr; + uint32 mxcsr_mask; + union { + x86_64_fp_register fp_registers[8]; // st0-st7 + x86_64_fp_register mmx_registers[8]; // mm0-mm7 + }; + x86_64_xmm_register xmm_registers[16]; // xmm0-xmm15 + uint8 reserved4[96]; // 416 - 512 +} x86_64_extended_registers; + + +struct x86_64_debug_cpu_state { + x86_64_extended_registers extended_registers; + + uint64 gs; + uint64 fs; + uint64 es; + uint64 ds; + uint64 r15; + uint64 r14; + uint64 r13; + uint64 r12; + uint64 r11; + uint64 r10; + uint64 r9; + uint64 r8; + uint64 rbp; + uint64 rsi; + uint64 rdi; + uint64 rdx; + uint64 rcx; + uint64 rbx; + uint64 rax; + uint64 vector; + uint64 error_code; + uint64 rip; + uint64 cs; + uint64 rflags; + uint64 rsp; + uint64 ss; +} __attribute__((aligned(16))); + + +#endif // _ARCH_X86_64_DEBUGGER_H diff --git a/headers/os/kernel/debugger.h b/headers/os/kernel/debugger.h index 5b86c706d0..c443b3977a 100644 --- a/headers/os/kernel/debugger.h +++ b/headers/os/kernel/debugger.h @@ -13,13 +13,16 @@ // include architecture specific definitions #include +#include #include #include #include #include -#ifdef __INTEL__ +#ifdef __x86_64__ + typedef struct x86_64_debug_cpu_state debug_cpu_state; +#elif __INTEL__ typedef struct x86_debug_cpu_state debug_cpu_state; #elif __POWERPC__ typedef struct ppc_debug_cpu_state debug_cpu_state; diff --git a/headers/private/kernel/arch/x86_64/arch_cpu.h b/headers/private/kernel/arch/x86_64/arch_cpu.h index dfdfe6ad73..f1d56b9fb5 100644 --- a/headers/private/kernel/arch/x86_64/arch_cpu.h +++ b/headers/private/kernel/arch/x86_64/arch_cpu.h @@ -1,6 +1,6 @@ -#ifndef _KERNEL_ARCH_x86_64_CPU_H -#define _KERNEL_ARCH_x86_64_CPU_H +#ifndef _KERNEL_ARCH_X86_64_CPU_H +#define _KERNEL_ARCH_X86_64_CPU_H #include "../x86/arch_cpu.h" -#endif /* _KERNEL_ARCH_x86_64_CPU_H */ +#endif /* _KERNEL_ARCH_X86_64_CPU_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_debug.h b/headers/private/kernel/arch/x86_64/arch_debug.h new file mode 100644 index 0000000000..6f06f95458 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_debug.h @@ -0,0 +1,17 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_DEBUG_H +#define _KERNEL_ARCH_X86_64_DEBUG_H + + +#include + + +struct arch_debug_registers { + uint64 rbp; +}; + + +#endif /* _KERNEL_ARCH_X86_64_DEBUG_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_int.h b/headers/private/kernel/arch/x86_64/arch_int.h index cd1f423f15..9507d6de6d 100644 --- a/headers/private/kernel/arch/x86_64/arch_int.h +++ b/headers/private/kernel/arch/x86_64/arch_int.h @@ -1,6 +1,78 @@ -#ifndef _KERNEL_ARCH_x86_64_INT_H -#define _KERNEL_ARCH_x86_64_INT_H +/* + * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_INT_H +#define _KERNEL_ARCH_X86_64_INT_H -#include "../x86/arch_int.h" -#endif /* _KERNEL_ARCH_x86_64_INT_H */ +#define ARCH_INTERRUPT_BASE 0x20 +#define NUM_IO_VECTORS (256 - ARCH_INTERRUPT_BASE) + + +static inline void +arch_int_enable_interrupts_inline(void) +{ + asm volatile("sti"); +} + + +static inline int +arch_int_disable_interrupts_inline(void) +{ + unsigned long flags; + + asm volatile("pushf;\n" + "pop %0;\n" + "cli" : "=g" (flags)); + return (flags & 0x200) != 0; +} + + +static inline void +arch_int_restore_interrupts_inline(int oldState) +{ + if (oldState) + asm("sti"); +} + + +static inline bool +arch_int_are_interrupts_enabled_inline(void) +{ + unsigned long flags; + + asm volatile("pushf;\n" + "pop %0;\n" : "=g" (flags)); + return (flags & 0x200) != 0; +} + + +// map the functions to the inline versions +#define arch_int_enable_interrupts() arch_int_enable_interrupts_inline() +#define arch_int_disable_interrupts() arch_int_disable_interrupts_inline() +#define arch_int_restore_interrupts(status) \ + arch_int_restore_interrupts_inline(status) +#define arch_int_are_interrupts_enabled() \ + arch_int_are_interrupts_enabled_inline() + + +#ifdef __cplusplus + +typedef struct interrupt_controller_s { + const char *name; + void (*enable_io_interrupt)(int32 num); + void (*disable_io_interrupt)(int32 num); + void (*configure_io_interrupt)(int32 num, uint32 config); + bool (*is_spurious_interrupt)(int32 num); + bool (*is_level_triggered_interrupt)(int32 num); + bool (*end_of_interrupt)(int32 num); +} interrupt_controller; + + +void arch_int_set_interrupt_controller(const interrupt_controller &controller); + +#endif // __cplusplus + +#endif /* _KERNEL_ARCH_X86_64_INT_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h index 40d55a3ac4..a7e45b34e7 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel.h @@ -1,6 +1,6 @@ -#ifndef _KERNEL_ARCH_x86_64_KERNEL_H -#define _KERNEL_ARCH_x86_64_KERNEL_H +#ifndef _KERNEL_ARCH_X86_64_KERNEL_H +#define _KERNEL_ARCH_X86_64_KERNEL_H #include "../x86/arch_kernel.h" -#endif /* _KERNEL_ARCH_x86_64_KERNEL_H */ +#endif /* _KERNEL_ARCH_X86_64_KERNEL_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel_args.h b/headers/private/kernel/arch/x86_64/arch_kernel_args.h index ecb2638c9a..78c54547e0 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel_args.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel_args.h @@ -1,6 +1,6 @@ -#ifndef _KERNEL_ARCH_x86_64_KERNEL_ARGS_H -#define _KERNEL_ARCH_x86_64_KERNEL_ARGS_H +#ifndef _KERNEL_ARCH_X86_64_KERNEL_ARGS_H +#define _KERNEL_ARCH_X86_64_KERNEL_ARGS_H #include "../x86/arch_kernel_args.h" -#endif /* _KERNEL_ARCH_x86_64_KERNEL_ARGS_H */ +#endif /* _KERNEL_ARCH_X86_64_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_system_info.h b/headers/private/kernel/arch/x86_64/arch_system_info.h index aeee330486..9137e0765f 100644 --- a/headers/private/kernel/arch/x86_64/arch_system_info.h +++ b/headers/private/kernel/arch/x86_64/arch_system_info.h @@ -1,6 +1,26 @@ -#ifndef _KERNEL_ARCH_x86_64_SYSTEM_INFO_H -#define _KERNEL_ARCH_x86_64_SYSTEM_INFO_H +/* + * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_SYSTEM_INFO_H +#define _KERNEL_ARCH_X86_64_SYSTEM_INFO_H -#include "../x86/arch_system_info.h" -#endif /* _KERNEL_ARCH_x86_64_SYSTEM_INFO_H */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +//status_t get_current_cpuid(cpuid_info *info, uint32 eax); +//uint32 get_eflags(void); +//void set_eflags(uint32 value); + +//status_t _user_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); + +#ifdef __cplusplus +} +#endif + +#endif /* _KRENEL_ARCH_X86_64_SYSTEM_INFO_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread.h b/headers/private/kernel/arch/x86_64/arch_thread.h index 0776b2865c..80f200a8c5 100644 --- a/headers/private/kernel/arch/x86_64/arch_thread.h +++ b/headers/private/kernel/arch/x86_64/arch_thread.h @@ -1,6 +1,32 @@ -#ifndef _KERNEL_ARCH_x86_64_THREAD_H -#define _KERNEL_ARCH_x86_64_THREAD_H +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_THREAD_H +#define _KERNEL_ARCH_X86_64_THREAD_H -#include "../x86/arch_thread.h" -#endif /* _KERNEL_ARCH_x86_64_THREAD_H */ +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +static inline Thread * +arch_thread_get_current_thread(void) +{ + return NULL; +} + +static inline void +arch_thread_set_current_thread(Thread *t) +{ + +} + +#ifdef __cplusplus +} +#endif + +#endif /* _KERNEL_ARCH_X86_64_THREAD_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread_types.h b/headers/private/kernel/arch/x86_64/arch_thread_types.h index f0dc013900..299371691a 100644 --- a/headers/private/kernel/arch/x86_64/arch_thread_types.h +++ b/headers/private/kernel/arch/x86_64/arch_thread_types.h @@ -1,6 +1,32 @@ -#ifndef _KERNEL_ARCH_x86_64_THREAD_TYPES_H -#define _KERNEL_ARCH_x86_64_THREAD_TYPES_H +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_THREAD_TYPES_H +#define _KERNEL_ARCH_X86_64_THREAD_TYPES_H -#include "../x86/arch_thread_types.h" -#endif /* _KERNEL_ARCH_x86_64_THREAD_TYPES_H */ +#include + + +// x86_64-specific thread information. +struct arch_thread { + // Stack pointer. + addr_t rsp; + + // FPU saved state - this must be 16 byte aligned. + uint8 fpu_state[512] __attribute__((aligned(16))); +} __attribute__((aligned(16))); + +struct arch_team { + // gcc treats empty structures as zero-length in C, but as if they contain + // a char in C++. So we have to put a dummy in to be able to use the struct + // from both in a consistent way. + char dummy; +}; + +struct arch_fork_arg { + struct iframe iframe; +}; + +#endif /* _KERNEL_ARCH_X86_64_THREAD_TYPES_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_user_debugger.h b/headers/private/kernel/arch/x86_64/arch_user_debugger.h index 9491ef5013..9053ec5e62 100644 --- a/headers/private/kernel/arch/x86_64/arch_user_debugger.h +++ b/headers/private/kernel/arch/x86_64/arch_user_debugger.h @@ -1,6 +1,6 @@ -#ifndef _KERNEL_ARCH_x86_64_USER_DEBUGGER_H -#define _KERNEL_ARCH_x86_64_USER_DEBUGGER_H +#ifndef _KERNEL_ARCH_X86_64_USER_DEBUGGER_H +#define _KERNEL_ARCH_X86_64_USER_DEBUGGER_H #include "../x86/arch_user_debugger.h" -#endif /* _KERNEL_ARCH_x86_64_USER_DEBUGGER_H */ +#endif /* _KERNEL_ARCH_X86_64_USER_DEBUGGER_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm.h b/headers/private/kernel/arch/x86_64/arch_vm.h new file mode 100644 index 0000000000..033d97d78b --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_vm.h @@ -0,0 +1,16 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_VM_H +#define _KERNEL_ARCH_X86_64_VM_H + +/* This many pages will be read/written on I/O if possible */ + +#define NUM_IO_PAGES 4 + /* 16 kB */ + +#define PAGE_SHIFT 12 + +#endif /* _KERNEL_ARCH_X86_64_VM_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h b/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h new file mode 100644 index 0000000000..98575cbe4c --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h @@ -0,0 +1,9 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H +#define _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H + + +#endif /* _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm_types.h b/headers/private/kernel/arch/x86_64/arch_vm_types.h new file mode 100644 index 0000000000..ab090369bc --- /dev/null +++ b/headers/private/kernel/arch/x86_64/arch_vm_types.h @@ -0,0 +1,9 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_VM_TYPES_H +#define _KERNEL_ARCH_X86_64_VM_TYPES_H + + +#endif /* _KERNEL_ARCH_X86_64_VM_TYPES_H */ diff --git a/headers/private/system/arch/x86_64/arch_commpage_defs.h b/headers/private/system/arch/x86_64/arch_commpage_defs.h new file mode 100644 index 0000000000..b2e2aff947 --- /dev/null +++ b/headers/private/system/arch/x86_64/arch_commpage_defs.h @@ -0,0 +1,15 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _SYSTEM_ARCH_x86_64_COMMPAGE_DEFS_H +#define _SYSTEM_ARCH_x86_64_COMMPAGE_DEFS_H + +#ifndef _SYSTEM_COMMPAGE_DEFS_H +# error Must not be included directly. Include instead! +#endif + +// FIXME: correct address +#define ARCH_USER_COMMPAGE_ADDR (0xffff0000) + +#endif /* _SYSTEM_ARCH_x86_64_COMMPAGE_DEFS_H */ diff --git a/headers/private/system/arch/x86_64/arch_real_time_data.h b/headers/private/system/arch/x86_64/arch_real_time_data.h new file mode 100644 index 0000000000..d6350c39f2 --- /dev/null +++ b/headers/private/system/arch/x86_64/arch_real_time_data.h @@ -0,0 +1,17 @@ +/* + * Copyright 2006, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_REAL_TIME_DATA_H +#define _KERNEL_ARCH_REAL_TIME_DATA_H + +#include +#include + + +struct arch_real_time_data { + bigtime_t system_time_offset; + uint32 system_time_conversion_factor; +}; + +#endif /* _KERNEL_ARCH_REAL_TIME_DATA_H */ diff --git a/src/system/kernel/arch/x86_64/Jamfile b/src/system/kernel/arch/x86_64/Jamfile new file mode 100644 index 0000000000..5f05fb5103 --- /dev/null +++ b/src/system/kernel/arch/x86_64/Jamfile @@ -0,0 +1,21 @@ +SubDir HAIKU_TOP src system kernel arch x86_64 ; + +SubDirHdrs [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) system kernel ] ; + # for syscall_numbers.h + +UsePrivateKernelHeaders ; +UsePrivateHeaders shared ; + +KernelMergeObject kernel_arch_x86_64.o : + arch_cpu.cpp + : + $(TARGET_KERNEL_PIC_CCFLAGS) +; + +CreateAsmStructOffsetsHeader asm_offsets.h : asm_offsets.cpp ; + +# We need to specify the dependency on the generated syscalls file explicitly. +#Includes [ FGristFiles arch_x86.S arch_interrupts.S ] +# : syscall_numbers.h ; +#Includes [ FGristFiles arch_interrupts.S ] +# : syscall_table.h ; diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp b/src/system/kernel/arch/x86_64/arch_cpu.cpp new file mode 100644 index 0000000000..0138f06af8 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_cpu.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +// #pragma mark - + + +status_t +arch_cpu_preboot_init_percpu(kernel_args *args, int cpu) +{ + return B_OK; +} + + +status_t +arch_cpu_init_percpu(kernel_args *args, int cpu) +{ + return B_OK; +} + + +status_t +arch_cpu_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_cpu_init_post_vm(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_cpu_init_post_modules(kernel_args *args) +{ + return B_OK; +} + + +void +arch_cpu_global_TLB_invalidate(void) +{ + +} + + +void +arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) +{ + +} + + +void +arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) +{ + +} + + +ssize_t +arch_cpu_user_strlcpy(char *to, const char *from, size_t size, + addr_t *faultHandler) +{ + int fromLength = 0; + addr_t oldFaultHandler = *faultHandler; + + // this check is to trick the gcc4 compiler and have it keep the error label + if (to == NULL && size > 0) + goto error; + + *faultHandler = (addr_t)&&error; + + if (size > 0) { + to[--size] = '\0'; + // copy + for ( ; size; size--, fromLength++, to++, from++) { + if ((*to = *from) == '\0') + break; + } + } + // count any leftover from chars + while (*from++ != '\0') { + fromLength++; + } + + *faultHandler = oldFaultHandler; + return fromLength; + +error: + *faultHandler = oldFaultHandler; + return B_BAD_ADDRESS; +} + + +status_t +arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) +{ + char *xs = (char *)s; + addr_t oldFaultHandler = *faultHandler; + + // this check is to trick the gcc4 compiler and have it keep the error label + if (s == NULL) + goto error; + + *faultHandler = (addr_t)&&error; + + while (count--) + *xs++ = c; + + *faultHandler = oldFaultHandler; + return 0; + +error: + *faultHandler = oldFaultHandler; + return B_BAD_ADDRESS; +} + + +status_t +arch_cpu_shutdown(bool rebootSystem) +{ + return B_ERROR; +} + + +void +arch_cpu_idle(void) +{ + asm("hlt"); +} + + +void +arch_cpu_sync_icache(void *address, size_t length) +{ + // instruction cache is always consistent on x86 +} + + +void +arch_cpu_memory_read_barrier(void) +{ + asm volatile ("lock;" : : : "memory"); + asm volatile ("addl $0, 0(%%esp);" : : : "memory"); +} + + +void +arch_cpu_memory_write_barrier(void) +{ + asm volatile ("lock;" : : : "memory"); + asm volatile ("addl $0, 0(%%esp);" : : : "memory"); +} + diff --git a/src/system/kernel/arch/x86_64/asm_offsets.cpp b/src/system/kernel/arch/x86_64/asm_offsets.cpp new file mode 100644 index 0000000000..1ac18010a4 --- /dev/null +++ b/src/system/kernel/arch/x86_64/asm_offsets.cpp @@ -0,0 +1,88 @@ +/* + * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +// This file is used to get C structure offsets into assembly code. +// The build system assembles the file and processes the output to create +// a header file with macro definitions, that can be included from assembly +// code. + + +#include + +//#include +//#include +//#include +//#include +//#include + + +#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value) + +#define DEFINE_OFFSET_MACRO(prefix, structure, member) \ + DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member)); + +#define DEFINE_SIZEOF_MACRO(prefix, structure) \ + DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure)); + + +void +dummy() +{ + // struct cpu_ent + //DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler); + //DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer); + + // struct Thread + //DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock); + //DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time); + //DEFINE_OFFSET_MACRO(THREAD, Thread, user_time); + //DEFINE_OFFSET_MACRO(THREAD, Thread, last_time); + //DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel); + //DEFINE_OFFSET_MACRO(THREAD, Thread, flags); + //DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top); + //DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); + + // struct iframe + //DEFINE_SIZEOF_MACRO(IFRAME, iframe); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, eax); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, edx); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, eip); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); + //DEFINE_OFFSET_MACRO(IFRAME, iframe, user_esp); + + // struct vm86_iframe + //DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); + //DEFINE_OFFSET_MACRO(VM86_IFRAME, vm86_iframe, flags); + + // struct syscall_info + //DEFINE_SIZEOF_MACRO(SYSCALL_INFO, syscall_info); + //DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, function); + //DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, parameter_size); + + // struct x86_optimized_functions + //DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, + // memcpy); + //DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, + // memset); + + // struct signal_frame_data + //DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data); + //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info); + //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context); + //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data); + //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler); + + // struct ucontext_t + //DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext); + + // struct vregs + //DEFINE_SIZEOF_MACRO(VREGS, vregs); + + // struct siginfo_t + //DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo); +} diff --git a/src/system/kernel/lib/arch/x86_64/Jamfile b/src/system/kernel/lib/arch/x86_64/Jamfile new file mode 100644 index 0000000000..2e43cfd19a --- /dev/null +++ b/src/system/kernel/lib/arch/x86_64/Jamfile @@ -0,0 +1,30 @@ +SubDir HAIKU_TOP src system kernel lib arch x86_64 ; + +SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; + +local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; +local posixSources = [ FDirName $(librootSources) posix ] ; + +SEARCH_SOURCE += [ FDirName $(librootSources) os arch $(TARGET_ARCH) ] ; + +KernelMergeObject kernel_os_arch_$(TARGET_ARCH).o : + atomic.S + byteorder.S + system_time_asm.S + system_time.c + + : $(TARGET_KERNEL_PIC_CCFLAGS) +; + +SEARCH_SOURCE += [ FDirName $(posixSources) arch $(TARGET_ARCH) ] ; + +KernelMergeObject kernel_lib_posix_arch_$(TARGET_ARCH).o : + siglongjmp.S + sigsetjmp.S + kernel_longjmp_return.c + kernel_setjmp_save_sigs.c + + arch_string.cpp + + : $(TARGET_KERNEL_PIC_CCFLAGS) +; diff --git a/src/system/kernel/lib/arch/x86_64/arch_string.cpp b/src/system/kernel/lib/arch/x86_64/arch_string.cpp new file mode 100644 index 0000000000..0c7e8a79c7 --- /dev/null +++ b/src/system/kernel/lib/arch/x86_64/arch_string.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. +*/ + +// TODO: Replace these with optimized implementations. + + +#include + + +void * +memcpy(void *dest, const void *src, size_t count) +{ + const unsigned char *s = src; + unsigned char *d = dest; + + for (; count != 0; count--) { + *d++ = *s++; + } + + return dest; +} + + +void * +memset(void *dest, int val, size_t count) +{ + unsigned char *d = dest; + + for (; count != 0; count--) { + *d++ = static_cast(val); + } + + return dest; +} From 11d3892d285a72e161f5b13365dcce6e05a32374 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 14 Jun 2012 13:06:55 +0100 Subject: [PATCH 007/273] Changed ICI data argument types from uint32 to addr_t. Since ICI arguments are used to send addresses in some places, uint32 is not sufficient on x86_64. addr_t still refers to the same type as uint32 (unsigned long) on other platforms, so this change only really affects x86_64. --- headers/private/kernel/smp.h | 12 +++---- .../arch/arm/paging/ARMVMTranslationMap.cpp | 4 +-- .../arch/m68k/paging/M68KVMTranslationMap.cpp | 4 +-- .../kernel/arch/x86/arch_system_info.cpp | 2 +- .../arch/x86/paging/X86VMTranslationMap.cpp | 4 +-- src/system/kernel/smp.cpp | 35 +++++++++---------- 6 files changed, 30 insertions(+), 31 deletions(-) diff --git a/headers/private/kernel/smp.h b/headers/private/kernel/smp.h index 9483adfada..aa19ad35d9 100644 --- a/headers/private/kernel/smp.h +++ b/headers/private/kernel/smp.h @@ -34,7 +34,7 @@ enum { typedef uint32 cpu_mask_t; -typedef void (*smp_call_func)(uint32 data1, int32 currentCPU, uint32 data2, uint32 data3); +typedef void (*smp_call_func)(addr_t data1, int32 currentCPU, addr_t data2, addr_t data3); #ifdef __cplusplus @@ -49,14 +49,14 @@ status_t smp_init_post_generic_syscalls(void); bool smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous); void smp_wake_up_non_boot_cpus(void); void smp_cpu_rendezvous(volatile uint32 *var, int current_cpu); -void smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, uint32 data3, +void smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2, addr_t data3, void *data_ptr, uint32 flags); -void smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, uint32 data, - uint32 data2, uint32 data3, void *data_ptr, uint32 flags); -void smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3, +void smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, addr_t data, + addr_t data2, addr_t data3, void *data_ptr, uint32 flags); +void smp_send_broadcast_ici(int32 message, addr_t data, addr_t data2, addr_t data3, void *data_ptr, uint32 flags); void smp_send_broadcast_ici_interrupts_disabled(int32 currentCPU, int32 message, - uint32 data, uint32 data2, uint32 data3, void *data_ptr, uint32 flags); + addr_t data, addr_t data2, addr_t data3, void *data_ptr, uint32 flags); int32 smp_get_num_cpus(void); void smp_set_num_cpus(int32 numCPUs); diff --git a/src/system/kernel/arch/arm/paging/ARMVMTranslationMap.cpp b/src/system/kernel/arch/arm/paging/ARMVMTranslationMap.cpp index ca5b73777a..1f94eba8ee 100644 --- a/src/system/kernel/arch/arm/paging/ARMVMTranslationMap.cpp +++ b/src/system/kernel/arch/arm/paging/ARMVMTranslationMap.cpp @@ -128,7 +128,7 @@ ARMVMTranslationMap::Flush() if (fIsKernelMap) { smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } else { int cpu = smp_get_current_cpu(); @@ -136,7 +136,7 @@ ARMVMTranslationMap::Flush() & ~((uint32)1 << cpu); if (cpuMask != 0) { smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } } diff --git a/src/system/kernel/arch/m68k/paging/M68KVMTranslationMap.cpp b/src/system/kernel/arch/m68k/paging/M68KVMTranslationMap.cpp index 8efa64aa3d..47fc0b274f 100644 --- a/src/system/kernel/arch/m68k/paging/M68KVMTranslationMap.cpp +++ b/src/system/kernel/arch/m68k/paging/M68KVMTranslationMap.cpp @@ -128,7 +128,7 @@ M68KVMTranslationMap::Flush() if (fIsKernelMap) { smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } else { int cpu = smp_get_current_cpu(); @@ -136,7 +136,7 @@ M68KVMTranslationMap::Flush() & ~((uint32)1 << cpu); if (cpuMask != 0) { smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } } diff --git a/src/system/kernel/arch/x86/arch_system_info.cpp b/src/system/kernel/arch/x86/arch_system_info.cpp index 3f2eb22ceb..8789dca0f4 100644 --- a/src/system/kernel/arch/x86/arch_system_info.cpp +++ b/src/system/kernel/arch/x86/arch_system_info.cpp @@ -50,7 +50,7 @@ get_cpuid(cpuid_info *info, uint32 eaxRegister, uint32 forCPU) // that the CPU supports cpuid. if (!get_cpuid_for(info, smp_get_current_cpu(), eaxRegister, forCPU)) { - smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (uint32)info, + smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)info, eaxRegister, forCPU, (void *)get_cpuid_for, SMP_MSG_FLAG_SYNC); } diff --git a/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp b/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp index 393ca4eda7..a9768653ef 100644 --- a/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp +++ b/src/system/kernel/arch/x86/paging/X86VMTranslationMap.cpp @@ -128,7 +128,7 @@ X86VMTranslationMap::Flush() if (fIsKernelMap) { smp_send_broadcast_ici(SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } else { int cpu = smp_get_current_cpu(); @@ -136,7 +136,7 @@ X86VMTranslationMap::Flush() & ~((uint32)1 << cpu); if (cpuMask != 0) { smp_send_multicast_ici(cpuMask, SMP_MSG_INVALIDATE_PAGE_LIST, - (uint32)fInvalidPages, fInvalidPagesCount, 0, NULL, + (addr_t)fInvalidPages, fInvalidPagesCount, 0, NULL, SMP_MSG_FLAG_SYNC); } } diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 7c4a6b963f..6095014f51 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -58,9 +58,9 @@ struct smp_msg { struct smp_msg *next; int32 message; - uint32 data; - uint32 data2; - uint32 data3; + addr_t data; + addr_t data2; + addr_t data3; void *data_ptr; uint32 flags; int32 ref_count; @@ -272,9 +272,9 @@ dump_ici_message(int argc, char** argv) kprintf("ICI message %p:\n", message); kprintf(" next: %p\n", message->next); kprintf(" message: %" B_PRId32 "\n", message->message); - kprintf(" data: %" B_PRIu32 "\n", message->data); - kprintf(" data2: %" B_PRIu32 "\n", message->data2); - kprintf(" data3: %" B_PRIu32 "\n", message->data3); + kprintf(" data: 0x%lx\n", message->data); + kprintf(" data2: 0x%lx\n", message->data2); + kprintf(" data3: 0x%lx\n", message->data3); kprintf(" data_ptr: %p\n", message->data_ptr); kprintf(" flags: %" B_PRIx32 "\n", message->flags); kprintf(" ref_count: %" B_PRIx32 "\n", message->ref_count); @@ -716,8 +716,7 @@ process_pending_ici(int32 currentCPU) switch (msg->message) { case SMP_MSG_INVALIDATE_PAGE_RANGE: - arch_cpu_invalidate_TLB_range((addr_t)msg->data, - (addr_t)msg->data2); + arch_cpu_invalidate_TLB_range(msg->data, msg->data2); break; case SMP_MSG_INVALIDATE_PAGE_LIST: arch_cpu_invalidate_TLB_list((addr_t*)msg->data, (int)msg->data2); @@ -755,8 +754,8 @@ process_pending_ici(int32 currentCPU) } default: - dprintf("smp_intercpu_int_handler: got unknown message %" B_PRId32 - "\n", msg->message); + dprintf("smp_intercpu_int_handler: got unknown message %" B_PRId32 "\n", + msg->message); break; } @@ -861,8 +860,8 @@ smp_intercpu_int_handler(int32 cpu) void -smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, - uint32 data3, void* dataPointer, uint32 flags) +smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2, + addr_t data3, void* dataPointer, addr_t flags) { struct smp_msg *msg; @@ -921,8 +920,8 @@ smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, void -smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, uint32 data, - uint32 data2, uint32 data3, void *dataPointer, uint32 flags) +smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, addr_t data, + addr_t data2, addr_t data3, void *dataPointer, uint32 flags) { if (!sICIEnabled) return; @@ -984,7 +983,7 @@ smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, uint32 data, void -smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3, +smp_send_broadcast_ici(int32 message, addr_t data, addr_t data2, addr_t data3, void *dataPointer, uint32 flags) { struct smp_msg *msg; @@ -1052,7 +1051,7 @@ smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3, void smp_send_broadcast_ici_interrupts_disabled(int32 currentCPU, int32 message, - uint32 data, uint32 data2, uint32 data3, void *dataPointer, uint32 flags) + addr_t data, addr_t data2, addr_t data3, void *dataPointer, uint32 flags) { if (!sICIEnabled) return; @@ -1276,7 +1275,7 @@ call_all_cpus(void (*func)(void*, int), void* cookie) } if (smp_get_num_cpus() > 1) { - smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (uint32)cookie, + smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)cookie, 0, 0, (void*)func, SMP_MSG_FLAG_ASYNC); } @@ -1300,7 +1299,7 @@ call_all_cpus_sync(void (*func)(void*, int), void* cookie) } if (smp_get_num_cpus() > 1) { - smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (uint32)cookie, + smp_send_broadcast_ici(SMP_MSG_CALL_FUNCTION, (addr_t)cookie, 0, 0, (void*)func, SMP_MSG_FLAG_SYNC); } From 40e20c10768c3dcfc54074b8886e3e91455332e1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 14 Jun 2012 14:18:50 +0100 Subject: [PATCH 008/273] Added gensyscalls headers for x86_64. --- src/tools/gensyscalls/arch/x86_64/arch_gensyscalls.h | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/tools/gensyscalls/arch/x86_64/arch_gensyscalls.h diff --git a/src/tools/gensyscalls/arch/x86_64/arch_gensyscalls.h b/src/tools/gensyscalls/arch/x86_64/arch_gensyscalls.h new file mode 100644 index 0000000000..620802d3a9 --- /dev/null +++ b/src/tools/gensyscalls/arch/x86_64/arch_gensyscalls.h @@ -0,0 +1,2 @@ +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE long +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE long From 4be4fc6b1faddbd037146214a0011d320842b4f3 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 16:04:20 +0100 Subject: [PATCH 009/273] More 64-bit compilation/safety fixes. --- src/system/kernel/debug/debug.cpp | 32 ++--- .../kernel/debug/debug_builtin_commands.cpp | 2 +- src/system/kernel/debug/debug_parser.cpp | 4 +- src/system/kernel/debug/gdb.cpp | 4 +- src/system/kernel/debug/tracing.cpp | 4 +- src/system/kernel/debug/user_debugger.cpp | 13 ++- .../kernel/device_manager/FileDevice.cpp | 2 +- src/system/kernel/device_manager/IOCache.cpp | 2 +- .../kernel/device_manager/IORequest.cpp | 10 +- .../device_manager/IOSchedulerSimple.cpp | 8 +- src/system/kernel/device_manager/devfs.cpp | 8 +- .../kernel/device_manager/device_manager.cpp | 18 +-- .../kernel/device_manager/dma_resources.cpp | 2 +- .../kernel/device_manager/id_generator.cpp | 2 +- .../kernel/device_manager/legacy_drivers.cpp | 25 ++-- .../disk_device_manager/KDiskDevice.cpp | 4 +- .../KDiskDeviceManager.cpp | 12 +- .../disk_device_manager/KFileDiskDevice.cpp | 2 +- .../kernel/disk_device_manager/KPartition.cpp | 28 ++--- .../disk_device_manager.cpp | 10 +- src/system/kernel/fs/socket.cpp | 2 +- src/system/kernel/fs/vfs.cpp | 110 +++++++++--------- src/system/kernel/fs/vfs_boot.cpp | 3 +- src/system/kernel/fs/vfs_request_io.cpp | 14 +-- .../kernel/lib/arch/x86_64/arch_string.cpp | 6 +- src/system/kernel/lib/kernel_vsprintf.cpp | 2 +- src/system/kernel/locks/lock.cpp | 24 ++-- src/system/kernel/posix/xsi_message_queue.cpp | 10 +- src/system/kernel/posix/xsi_semaphore.cpp | 8 +- src/system/kernel/scheduler/scheduler.cpp | 2 +- .../kernel/scheduler/scheduler_affine.cpp | 6 +- .../kernel/scheduler/scheduler_simple.cpp | 4 +- .../kernel/scheduler/scheduler_simple_smp.cpp | 4 +- src/system/kernel/slab/MemoryManager.cpp | 2 +- src/system/kernel/slab/Slab.cpp | 6 +- src/system/kernel/team.cpp | 33 +++--- src/system/kernel/thread.cpp | 73 ++++++------ src/system/kernel/util/khash.cpp | 4 +- src/system/kernel/vm/VMAnonymousCache.cpp | 17 +-- src/system/kernel/vm/VMCache.cpp | 14 +-- src/system/kernel/vm/VMUserAddressSpace.cpp | 9 +- src/system/kernel/vm/vm.cpp | 73 ++++++------ src/system/kernel/vm/vm_page.cpp | 6 +- src/system/libroot/posix/stdlib/strtod.c | 3 +- 44 files changed, 326 insertions(+), 301 deletions(-) diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 89e0b3b584..64810c204d 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -264,7 +264,7 @@ insert_chars_into_line(char* buffer, int32& position, int32& length, // reposition cursor, if necessary if (position < length) - kprintf("\x1b[%ldD", length - position); + kprintf("\x1b[%" B_PRId32 "D", length - position); } @@ -296,7 +296,7 @@ remove_char_from_line(char* buffer, int32& position, int32& length) kputchar(' '); // reposition the cursor - kprintf("\x1b[%ldD", length - position + 1); + kprintf("\x1b[%" B_PRId32 "D", length - position + 1); } @@ -439,7 +439,7 @@ public: if (reprintLine) { kprintf("%s%.*s", kKDLPrompt, (int)length, buffer); if (position < length) - kprintf("\x1b[%ldD", length - position); + kprintf("\x1b[%" B_PRId32 "D", length - position); } } }; @@ -488,7 +488,7 @@ read_line(char* buffer, int32 maxLength, kputchar(' '); // reposition cursor - kprintf("\x1b[%ldD", length - position); + kprintf("\x1b[%" B_PRId32 "D", length - position); length = position; } @@ -566,7 +566,7 @@ read_line(char* buffer, int32 maxLength, // swap the current line with something from the history if (position > 0) - kprintf("\x1b[%ldD", position); // move to beginning of line + kprintf("\x1b[%" B_PRId32 "D", position); // move to beginning of line strcpy(buffer, sLineBuffer[historyLine]); length = position = strlen(buffer); @@ -608,7 +608,7 @@ read_line(char* buffer, int32 maxLength, length = strlen(buffer); kprintf("%s\x1b[K", buffer + position); // print the line and clear the rest - kprintf("\x1b[%ldD", length - position); + kprintf("\x1b[%" B_PRId32 "D", length - position); // reposition cursor currentHistoryLine = historyLine; @@ -617,7 +617,7 @@ read_line(char* buffer, int32 maxLength, case 'H': // home { if (position > 0) { - kprintf("\x1b[%ldD", position); + kprintf("\x1b[%" B_PRId32 "D", position); position = 0; } break; @@ -625,7 +625,7 @@ read_line(char* buffer, int32 maxLength, case 'F': // end { if (position < length) { - kprintf("\x1b[%ldC", length - position); + kprintf("\x1b[%" B_PRId32 "C", length - position); position = length; } break; @@ -825,10 +825,10 @@ kernel_debugger_loop(const char* messagePrefix, const char* message, Thread* thread = thread_get_current_thread(); if (thread == NULL) { - kprintf("Running on CPU %ld\n", sDebuggerOnCPU); + kprintf("Running on CPU %" B_PRId32 "\n", sDebuggerOnCPU); } else if (!debug_is_kernel_memory_accessible((addr_t)thread, sizeof(Thread), B_KERNEL_READ_AREA)) { - kprintf("Running on CPU %ld\n", sDebuggerOnCPU); + kprintf("Running on CPU %" B_PRId32 "\n", sDebuggerOnCPU); kprintf("Current thread pointer is %p, which is an address we " "can't read from.\n", thread); arch_debug_unset_current_thread(); @@ -836,8 +836,8 @@ kernel_debugger_loop(const char* messagePrefix, const char* message, set_debug_variable("_thread", (uint64)(addr_t)thread); set_debug_variable("_threadID", thread->id); - kprintf("Thread %ld \"%.64s\" running on CPU %ld\n", thread->id, - thread->name, sDebuggerOnCPU); + kprintf("Thread %" B_PRId32 " \"%.64s\" running on CPU %" B_PRId32 "\n", + thread->id, thread->name, sDebuggerOnCPU); if (thread->cpu != gCPU + cpu) { kprintf("The thread's CPU pointer is %p, but should be %p.\n", @@ -1159,7 +1159,7 @@ cmd_switch_cpu(int argc, char** argv) } if (argc == 1) { - kprintf("running on CPU %ld\n", smp_get_current_cpu()); + kprintf("running on CPU %" B_PRId32 "\n", smp_get_current_cpu()); return 0; } @@ -1170,7 +1170,7 @@ cmd_switch_cpu(int argc, char** argv) } if (newCPU == smp_get_current_cpu()) { - kprintf("already running on CPU %ld\n", newCPU); + kprintf("already running on CPU %" B_PRId32 "\n", newCPU); return 0; } @@ -1409,7 +1409,7 @@ syslog_init_post_vm(struct kernel_args* args) "Welcome to syslog debug output!\nHaiku revision: %s\n", get_haiku_revision()); syslog_write(revisionBuffer, - std::min(length, (ssize_t)sizeof(revisionBuffer) - 1), false); + std::min(length, (int32)sizeof(revisionBuffer) - 1), false); add_debugger_command_etc("syslog", &cmd_dump_syslog, "Dumps the syslog buffer.", @@ -1522,7 +1522,7 @@ flush_pending_repeats(bool notifySyslog) if (sMessageRepeatCount > 1) { static char temp[40]; size_t length = snprintf(temp, sizeof(temp), - "Last message repeated %ld times.\n", sMessageRepeatCount); + "Last message repeated %" B_PRId32 " times.\n", sMessageRepeatCount); length = std::min(length, sizeof(temp) - 1); if (sSerialDebugEnabled) diff --git a/src/system/kernel/debug/debug_builtin_commands.cpp b/src/system/kernel/debug/debug_builtin_commands.cpp index bb0fe2857a..32f7445783 100644 --- a/src/system/kernel/debug/debug_builtin_commands.cpp +++ b/src/system/kernel/debug/debug_builtin_commands.cpp @@ -108,7 +108,7 @@ cmd_error(int argc, char **argv) } int32 error = parse_expression(argv[1]); - kprintf("error 0x%lx: %s\n", error, strerror(error)); + kprintf("error 0x%" B_PRIx32 ": %s\n", error, strerror(error)); return 0; } diff --git a/src/system/kernel/debug/debug_parser.cpp b/src/system/kernel/debug/debug_parser.cpp index 08cdee8d45..87f50c5474 100644 --- a/src/system/kernel/debug/debug_parser.cpp +++ b/src/system/kernel/debug/debug_parser.cpp @@ -130,8 +130,8 @@ parse_exception(const char* message, int32 position) { if (sNextJumpBufferIndex == 0) { kprintf_unfiltered("parse_exception(): No jump buffer!\n"); - kprintf_unfiltered("exception: \"%s\", position: %lu\n", message, - position); + kprintf_unfiltered("exception: \"%s\", position: %" B_PRId32 "\n", + message, position); return; } diff --git a/src/system/kernel/debug/gdb.cpp b/src/system/kernel/debug/gdb.cpp index 81ba8a0be5..3711683027 100644 --- a/src/system/kernel/debug/gdb.cpp +++ b/src/system/kernel/debug/gdb.cpp @@ -252,8 +252,8 @@ gdb_parse_command(void) case 'm': { char* ptr; - unsigned address; - unsigned len; + addr_t address; + size_t len; // The 'm' command has the form mAAA,LLL // where AAA is the address and LLL is the diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index 72cbb959aa..3ec01ee14d 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -806,9 +806,9 @@ AbstractTraceEntry::Dump(TraceOutput& out) : fTime; if (out.Flags() & TRACE_OUTPUT_TEAM_ID) - out.Print("[%6ld:%6ld] %10Ld: ", fThread, fTeam, time); + out.Print("[%6" B_PRId32 ":%6" B_PRId32 "] %10Ld: ", fThread, fTeam, time); else - out.Print("[%6ld] %10Ld: ", fThread, time); + out.Print("[%6" B_PRId32 "] %10Ld: ", fThread, time); AddDump(out); diff --git a/src/system/kernel/debug/user_debugger.cpp b/src/system/kernel/debug/user_debugger.cpp index ebb173673e..2c6a515c19 100644 --- a/src/system/kernel/debug/user_debugger.cpp +++ b/src/system/kernel/debug/user_debugger.cpp @@ -540,7 +540,7 @@ thread_hit_debug_event_internal(debug_debugger_message event, port_id port = -1; if (setPort) { char nameBuffer[128]; - snprintf(nameBuffer, sizeof(nameBuffer), "nub to thread %ld", + snprintf(nameBuffer, sizeof(nameBuffer), "nub to thread %" B_PRId32, thread->id); port = create_port(1, nameBuffer); @@ -811,7 +811,7 @@ thread_hit_serious_debug_event(debug_debugger_message event, if (error != B_OK) { Thread *thread = thread_get_current_thread(); dprintf("thread_hit_serious_debug_event(): Failed to install debugger: " - "thread: %ld: %s\n", thread->id, strerror(error)); + "thread: %" B_PRId32 ": %s\n", thread->id, strerror(error)); return error; } @@ -2632,14 +2632,14 @@ install_team_debugger(team_id teamID, port_id debuggerPort, // create the debugger write lock semaphore char nameBuffer[B_OS_NAME_LENGTH]; - snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debugger port write", - teamID); + snprintf(nameBuffer, sizeof(nameBuffer), "team %" B_PRId32 " debugger port " + "write", teamID); sem_id debuggerWriteLock = create_sem(1, nameBuffer); if (debuggerWriteLock < 0) error = debuggerWriteLock; // create the nub port - snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug", teamID); + snprintf(nameBuffer, sizeof(nameBuffer), "team %" B_PRId32 " debug", teamID); if (error == B_OK) { nubPort = create_port(1, nameBuffer); if (nubPort < 0) @@ -2666,7 +2666,8 @@ install_team_debugger(team_id teamID, port_id debuggerPort, // spawn the nub thread thread_id nubThread = -1; if (error == B_OK) { - snprintf(nameBuffer, sizeof(nameBuffer), "team %ld debug task", teamID); + snprintf(nameBuffer, sizeof(nameBuffer), "team %" B_PRId32 " debug task", + teamID); nubThread = spawn_kernel_thread_etc(debug_nub_thread, nameBuffer, B_NORMAL_PRIORITY, NULL, teamID); if (nubThread < 0) diff --git a/src/system/kernel/device_manager/FileDevice.cpp b/src/system/kernel/device_manager/FileDevice.cpp index 0f76dae5f4..3522db5249 100644 --- a/src/system/kernel/device_manager/FileDevice.cpp +++ b/src/system/kernel/device_manager/FileDevice.cpp @@ -232,7 +232,7 @@ FileDevice::Control(void* _cookie, int32 op, void* buffer, size_t length) switch (op) { case B_GET_DEVICE_SIZE: return set_ioctl_result( - fFileSize > ~(size_t)0 ? ~(size_t)0 : (size_t)fFileSize, + (uint64)fFileSize > (uint64)(~(size_t)0) ? ~(size_t)0 : (size_t)fFileSize, buffer, length); case B_SET_BLOCKING_IO: diff --git a/src/system/kernel/device_manager/IOCache.cpp b/src/system/kernel/device_manager/IOCache.cpp index 2617cf18d4..a65e515d28 100644 --- a/src/system/kernel/device_manager/IOCache.cpp +++ b/src/system/kernel/device_manager/IOCache.cpp @@ -243,7 +243,7 @@ IOCache::_DoRequest(IORequest* request, generic_size_t& _bytesTransferred) off_t lineOffset = (offset >> fLineSizeShift) << fLineSizeShift; // intersection of request and cache line - off_t cacheLineEnd = std::min(lineOffset + fLineSize, fDeviceCapacity); + off_t cacheLineEnd = std::min(lineOffset + (off_t)fLineSize, fDeviceCapacity); size_t requestLineLength = std::min(cacheLineEnd - offset, (off_t)length); diff --git a/src/system/kernel/device_manager/IORequest.cpp b/src/system/kernel/device_manager/IORequest.cpp index e470103346..494417ff36 100644 --- a/src/system/kernel/device_manager/IORequest.cpp +++ b/src/system/kernel/device_manager/IORequest.cpp @@ -1285,15 +1285,15 @@ IORequest::Dump() const kprintf(" length: %" B_PRIuGENADDR "\n", fLength); kprintf(" transfer size: %" B_PRIuGENADDR "\n", fTransferSize); kprintf(" relative offset: %" B_PRIuGENADDR "\n", fRelativeParentOffset); - kprintf(" pending children: %ld\n", fPendingChildren); - kprintf(" flags: %#lx\n", fFlags); - kprintf(" team: %ld\n", fTeam); - kprintf(" thread: %ld\n", fThread); + kprintf(" pending children: %" B_PRId32 "\n", fPendingChildren); + kprintf(" flags: %#" B_PRIx32 "\n", fFlags); + kprintf(" team: %" B_PRId32 "\n", fTeam); + kprintf(" thread: %" B_PRId32 "\n", fThread); kprintf(" r/w: %s\n", fIsWrite ? "write" : "read"); kprintf(" partial transfer: %s\n", fPartialTransfer ? "yes" : "no"); kprintf(" finished cvar: %p\n", &fFinishedCondition); kprintf(" iteration:\n"); - kprintf(" vec index: %lu\n", fVecIndex); + kprintf(" vec index: %" B_PRIu32 "\n", fVecIndex); kprintf(" vec offset: %" B_PRIuGENADDR "\n", fVecOffset); kprintf(" remaining bytes: %" B_PRIuGENADDR "\n", fRemainingBytes); kprintf(" callbacks:\n"); diff --git a/src/system/kernel/device_manager/IOSchedulerSimple.cpp b/src/system/kernel/device_manager/IOSchedulerSimple.cpp index 07bd88a06f..34e62ba583 100644 --- a/src/system/kernel/device_manager/IOSchedulerSimple.cpp +++ b/src/system/kernel/device_manager/IOSchedulerSimple.cpp @@ -38,9 +38,9 @@ void IORequestOwner::Dump() const { kprintf("IORequestOwner at %p\n", this); - kprintf(" team: %ld\n", team); - kprintf(" thread: %ld\n", thread); - kprintf(" priority: %ld\n", priority); + kprintf(" team: %" B_PRId32 "\n", team); + kprintf(" thread: %" B_PRId32 "\n", thread); + kprintf(" priority: %" B_PRId32 "\n", priority); kprintf(" requests:"); for (IORequestList::ConstIterator it = requests.GetIterator(); @@ -654,7 +654,7 @@ IOSchedulerSimple::_Scheduler() if (request == NULL) { resourcesAvailable = false; if (operationCount == 0) -panic("no more requests for owner %p (thread %ld)", owner, owner->thread); +panic("no more requests for owner %p (thread %" B_PRId32 ")", owner, owner->thread); break; } diff --git a/src/system/kernel/device_manager/devfs.cpp b/src/system/kernel/device_manager/devfs.cpp index a1e0411138..efb66e3fa3 100644 --- a/src/system/kernel/device_manager/devfs.cpp +++ b/src/system/kernel/device_manager/devfs.cpp @@ -809,7 +809,7 @@ dump_node(int argc, char** argv) kprintf(" dir next: %p\n", vnode->dir_next); if (S_ISDIR(vnode->stream.type)) { - kprintf(" dir scanned: %ld\n", vnode->stream.u.dir.scanned); + kprintf(" dir scanned: %" B_PRId32 "\n", vnode->stream.u.dir.scanned); kprintf(" contents:\n"); devfs_vnode* children = vnode->stream.u.dir.dir_head; @@ -828,9 +828,9 @@ dump_node(int argc, char** argv) vnode->stream.u.dev.partition->raw_device); kprintf(" offset: %Ld\n", info.offset); kprintf(" size: %Ld\n", info.size); - kprintf(" block size: %ld\n", info.logical_block_size); - kprintf(" session: %ld\n", info.session); - kprintf(" partition: %ld\n", info.partition); + kprintf(" block size: %" B_PRId32 "\n", info.logical_block_size); + kprintf(" session: %" B_PRId32 "\n", info.session); + kprintf(" partition: %" B_PRId32 "\n", info.partition); kprintf(" device: %s\n", info.device); set_debug_variable("_raw", (addr_t)vnode->stream.u.dev.partition->raw_device); diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index 93f811505c..239ac4bb6e 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -263,19 +263,23 @@ dump_attribute(device_attr* attr, int32 level) break; case B_INT8_TYPE: case B_UINT8_TYPE: - kprintf("uint8 : %u (%#x)", attr->value.ui8, attr->value.ui8); + kprintf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8, + attr->value.ui8); break; case B_INT16_TYPE: case B_UINT16_TYPE: - kprintf("uint16 : %u (%#x)", attr->value.ui16, attr->value.ui16); + kprintf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16, + attr->value.ui16); break; case B_INT32_TYPE: case B_UINT32_TYPE: - kprintf("uint32 : %lu (%#lx)", attr->value.ui32, attr->value.ui32); + kprintf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32, + attr->value.ui32); break; case B_INT64_TYPE: case B_UINT64_TYPE: - kprintf("uint64 : %Lu (%#Lx)", attr->value.ui64, attr->value.ui64); + kprintf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64, + attr->value.ui64); break; default: kprintf("raw data"); @@ -2167,9 +2171,9 @@ void device_node::Dump(int32 level) { put_level(level); - kprintf("(%ld) @%p \"%s\" (ref %ld, init %ld, module %p, data %p)\n", level, - this, ModuleName(), fRefCount, fInitialized, DriverModule(), - DriverData()); + kprintf("(%" B_PRId32 ") @%p \"%s\" (ref %" B_PRId32 ", init %" B_PRId32 + ", module %p, data %p)\n", level, this, ModuleName(), fRefCount, + fInitialized, DriverModule(), DriverData()); AttributeList::Iterator attribute = Attributes().GetIterator(); while (attribute.HasNext()) { diff --git a/src/system/kernel/device_manager/dma_resources.cpp b/src/system/kernel/device_manager/dma_resources.cpp index 5c4b3de920..7e334f4e21 100644 --- a/src/system/kernel/device_manager/dma_resources.cpp +++ b/src/system/kernel/device_manager/dma_resources.cpp @@ -79,7 +79,7 @@ DMABuffer::Dump() const kprintf(" bounce buffer: %p (physical %#" B_PRIxPHYSADDR ")\n", fBounceBuffer->address, fBounceBuffer->physical_address); kprintf(" bounce buffer size: %" B_PRIxPHYSADDR "\n", fBounceBuffer->size); - kprintf(" vecs: %lu\n", fVecCount); + kprintf(" vecs: %" B_PRIu32 "\n", fVecCount); for (uint32 i = 0; i < fVecCount; i++) { kprintf(" [%" B_PRIu32 "] %#" B_PRIxGENADDR ", %" B_PRIuGENADDR "\n", diff --git a/src/system/kernel/device_manager/id_generator.cpp b/src/system/kernel/device_manager/id_generator.cpp index 9fadf6e709..29904a7fb7 100644 --- a/src/system/kernel/device_manager/id_generator.cpp +++ b/src/system/kernel/device_manager/id_generator.cpp @@ -225,7 +225,7 @@ dm_free_id(const char* name, uint32 id) // make sure it's really allocated // (very important to keep in sync if ((generator->alloc_map[id / 8] & (1 << (id & 7))) == 0) { - dprintf("id %ld of generator %s wasn't allocated\n", id, + dprintf("id %" B_PRIu32 " of generator %s wasn't allocated\n", id, generator->name); release_generator(generator); diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index 3c8e0cc66a..2274f721d8 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -370,8 +370,8 @@ load_driver(legacy_driver *driver) #error Add checks here for new vs old api version! #endif if (*apiVersion > B_CUR_DRIVER_API_VERSION) { - dprintf("devfs: \"%s\" api_version %ld not handled\n", driver->name, - *apiVersion); + dprintf("devfs: \"%s\" api_version %" B_PRId32 " not handled\n", + driver->name, *apiVersion); status = B_BAD_VALUE; goto error1; } @@ -664,8 +664,8 @@ load_driver_symbols(const char *driverName) static status_t reload_driver(legacy_driver *driver) { - dprintf("devfs: reload driver \"%s\" (%ld, %lld)\n", driver->name, - driver->device, driver->node); + dprintf("devfs: reload driver \"%s\" (%" B_PRIdDEV ", %lld)\n", + driver->name, driver->device, driver->node); unload_driver(driver); @@ -825,16 +825,16 @@ dump_driver(legacy_driver* driver) kprintf("DEVFS DRIVER: %p\n", driver); kprintf(" name: %s\n", driver->name); kprintf(" path: %s\n", driver->path); - kprintf(" image: %ld\n", driver->image); - kprintf(" device: %ld\n", driver->device); + kprintf(" image: %" B_PRId32 "\n", driver->image); + kprintf(" device: %" B_PRIdDEV "\n", driver->device); kprintf(" node: %Ld\n", driver->node); - kprintf(" last modified: %ld.%lu\n", driver->last_modified.tv_sec, + kprintf(" last modified: %" B_PRIdTIME ".%ld\n", driver->last_modified.tv_sec, driver->last_modified.tv_nsec); - kprintf(" devs used: %ld\n", driver->devices_used); - kprintf(" devs published: %ld\n", driver->devices.Count()); + kprintf(" devs used: %" B_PRIu32 "\n", driver->devices_used); + kprintf(" devs published: %" B_PRId32 "\n", driver->devices.Count()); kprintf(" binary updated: %d\n", driver->binary_updated); - kprintf(" priority: %ld\n", driver->priority); - kprintf(" api version: %ld\n", driver->api_version); + kprintf(" priority: %" B_PRId32 "\n", driver->priority); + kprintf(" api version: %" B_PRId32 "\n", driver->api_version); kprintf(" hooks: find_device %p, publish_devices %p\n" " uninit_driver %p, uninit_hardware %p\n", driver->find_device, driver->publish_devices, driver->uninit_driver, @@ -883,7 +883,8 @@ dump_driver(int argc, char** argv) if (driver == NULL) break; - kprintf("%p %5ld %3ld %5ld %c %3ld %s\n", driver, + kprintf("%p %5" B_PRId32 " %3" B_PRIu32 " %5" B_PRId32 " %c " + "%3" B_PRId32 " %s\n", driver, driver->image < 0 ? -1 : driver->image, driver->devices_used, driver->devices.Count(), driver->binary_updated ? 'U' : ' ', driver->priority, diff --git a/src/system/kernel/disk_device_manager/KDiskDevice.cpp b/src/system/kernel/disk_device_manager/KDiskDevice.cpp index b074b4d1c0..1d74c6d005 100644 --- a/src/system/kernel/disk_device_manager/KDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDevice.cpp @@ -346,9 +346,9 @@ KDiskDevice::WriteUserData(UserDataWriter& writer) void KDiskDevice::Dump(bool deep, int32 level) { - OUT("device %ld: %s\n", ID(), Path()); + OUT("device %" B_PRId32 ": %s\n", ID(), Path()); OUT(" media status: %s\n", strerror(fMediaStatus)); - OUT(" device flags: %lx\n", DeviceFlags()); + OUT(" device flags: %" B_PRIx32 "\n", DeviceFlags()); if (fMediaStatus == B_OK) KPartition::Dump(deep, 0); } diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp index 3916f1ae24..076a24bda4 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp @@ -261,7 +261,7 @@ KDiskDeviceManager::KDiskDeviceManager() if (fMediaChecker >= 0) resume_thread(fMediaChecker); - DBG(OUT("number of disk systems: %ld\n", CountDiskSystems())); + DBG(OUT("number of disk systems: %" B_PRId32 "\n", CountDiskSystems())); // TODO: Watch the disk systems and the relevant directories. } @@ -285,26 +285,26 @@ KDiskDeviceManager::~KDiskDeviceManager() // some sanity checks if (fPartitions->Count() > 0) { - DBG(OUT("WARNING: There are still %ld unremoved partitions!\n", + DBG(OUT("WARNING: There are still %" B_PRId32 " unremoved partitions!\n", fPartitions->Count())); for (PartitionMap::Iterator it = fPartitions->Begin(); it != fPartitions->End(); ++it) { - DBG(OUT(" partition: %ld\n", it->Value()->ID())); + DBG(OUT(" partition: %" B_PRId32 "\n", it->Value()->ID())); } } if (fObsoletePartitions->Count() > 0) { - DBG(OUT("WARNING: There are still %ld obsolete partitions!\n", + DBG(OUT("WARNING: There are still %" B_PRId32 " obsolete partitions!\n", fObsoletePartitions->Count())); for (PartitionSet::Iterator it = fObsoletePartitions->Begin(); it != fObsoletePartitions->End(); ++it) { - DBG(OUT(" partition: %ld\n", (*it)->ID())); + DBG(OUT(" partition: %" B_PRId32 "\n", (*it)->ID())); } } // remove all disk systems for (int32 cookie = 0; KDiskSystem* diskSystem = NextDiskSystem(&cookie);) { fDiskSystems->Remove(diskSystem->ID()); if (diskSystem->IsLoaded()) { - DBG(OUT("WARNING: Disk system `%s' (%ld) is still loaded!\n", + DBG(OUT("WARNING: Disk system `%s' (%" B_PRId32 ") is still loaded!\n", diskSystem->Name(), diskSystem->ID())); } else delete diskSystem; diff --git a/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp b/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp index bbf93e7d42..11248ac282 100644 --- a/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp +++ b/src/system/kernel/disk_device_manager/KFileDiskDevice.cpp @@ -212,7 +212,7 @@ KFileDiskDevice::_GetDirectoryPath(partition_id id, KPath* path) status_t error = path->SetPath(kFileDevicesDir); if (error == B_OK) { char idBuffer[12]; - snprintf(idBuffer, sizeof(idBuffer), "%ld", id); + snprintf(idBuffer, sizeof(idBuffer), "%" B_PRId32, id); error = path->Append(idBuffer); } return error; diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index aa60d9556e..dcaafb94af 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -216,7 +216,7 @@ KPartition::PublishDevice() error = devfs_publish_partition(buffer, &info); if (error != B_OK) { dprintf("KPartition::PublishDevice(): Failed to publish partition " - "%ld: %s\n", ID(), strerror(error)); + "%" B_PRId32 ": %s\n", ID(), strerror(error)); free(fPublishedName); fPublishedName = NULL; return error; @@ -237,14 +237,14 @@ KPartition::UnpublishDevice() status_t error = GetPath(&path); if (error != B_OK) { dprintf("KPartition::UnpublishDevice(): Failed to get path for " - "partition %ld: %s\n", ID(), strerror(error)); + "partition %" B_PRId32 ": %s\n", ID(), strerror(error)); return error; } error = devfs_unpublish_partition(path.Path()); if (error != B_OK) { dprintf("KPartition::UnpublishDevice(): Failed to unpublish partition " - "%ld: %s\n", ID(), strerror(error)); + "%" B_PRId32 ": %s\n", ID(), strerror(error)); } free(fPublishedName); @@ -285,7 +285,7 @@ KPartition::RepublishDevice() free(newName); UnpublishDevice(); dprintf("KPartition::RepublishDevice(): Failed to republish partition " - "%ld: %s\n", ID(), strerror(error)); + "%" B_PRId32 ": %s\n", ID(), strerror(error)); return error; } @@ -657,7 +657,7 @@ KPartition::GetFileName(char* buffer, size_t size) const { // If the parent is the device, the name is the index of the partition. if (Parent() == NULL || Parent()->IsDevice()) { - if (snprintf(buffer, size, "%ld", Index()) >= (int)size) + if (snprintf(buffer, size, "%" B_PRId32, Index()) >= (int)size) return B_NAME_TOO_LONG; return B_OK; } @@ -669,7 +669,7 @@ KPartition::GetFileName(char* buffer, size_t size) const return error; size_t len = strlen(buffer); - if (snprintf(buffer + len, size - len, "_%ld", Index()) >= int(size - len)) + if (snprintf(buffer + len, size - len, "_%" B_PRId32, Index()) >= int(size - len)) return B_NAME_TOO_LONG; return B_OK; } @@ -1172,7 +1172,7 @@ KPartition::UninitializeContents(bool logChanges) B_FORCE_UNMOUNT | B_UNMOUNT_BUSY_PARTITION); if (error != B_OK) { dprintf("KPartition::UninitializeContents(): Failed to unmount " - "device %ld: %s\n", VolumeID(), strerror(error)); + "device %" B_PRIdDEV ": %s\n", VolumeID(), strerror(error)); } SetVolumeID(-1); @@ -1302,17 +1302,17 @@ KPartition::Dump(bool deep, int32 level) KPath path; GetPath(&path); if (level > 0) - OUT("%spartition %ld: %s\n", prefix, ID(), path.Path()); + OUT("%spartition %" B_PRId32 ": %s\n", prefix, ID(), path.Path()); OUT("%s offset: %lld\n", prefix, Offset()); OUT("%s size: %lld (%.2f MB)\n", prefix, Size(), Size() / (1024.0*1024)); OUT("%s content size: %lld\n", prefix, ContentSize()); - OUT("%s block size: %lu\n", prefix, BlockSize()); - OUT("%s child count: %ld\n", prefix, CountChildren()); - OUT("%s index: %ld\n", prefix, Index()); - OUT("%s status: %lu\n", prefix, Status()); - OUT("%s flags: %lx\n", prefix, Flags()); - OUT("%s volume: %ld\n", prefix, VolumeID()); + OUT("%s block size: %" B_PRIu32 "\n", prefix, BlockSize()); + OUT("%s child count: %" B_PRId32 "\n", prefix, CountChildren()); + OUT("%s index: %" B_PRId32 "\n", prefix, Index()); + OUT("%s status: %" B_PRIu32 "\n", prefix, Status()); + OUT("%s flags: %" B_PRIx32 "\n", prefix, Flags()); + OUT("%s volume: %" B_PRIdDEV "\n", prefix, VolumeID()); OUT("%s disk system: %s\n", prefix, (DiskSystem() ? DiskSystem()->Name() : NULL)); OUT("%s name: %s\n", prefix, Name()); diff --git a/src/system/kernel/disk_device_manager/disk_device_manager.cpp b/src/system/kernel/disk_device_manager/disk_device_manager.cpp index 8d54fa7b49..421dc78f37 100644 --- a/src/system/kernel/disk_device_manager/disk_device_manager.cpp +++ b/src/system/kernel/disk_device_manager/disk_device_manager.cpp @@ -174,11 +174,11 @@ create_child_partition(partition_id partitionID, int32 index, off_t offset, == B_OK) { return child->PartitionData(); } else { - DBG(OUT(" creating child (%ld, %ld) failed\n", partitionID, - index)); + DBG(OUT(" creating child (%" B_PRId32 ", %" B_PRId32 ") failed\n", + partitionID, index)); } } else - DBG(OUT(" partition %ld not found\n", partitionID)); + DBG(OUT(" partition %" B_PRId32 " not found\n", partitionID)); return NULL; } @@ -244,8 +244,8 @@ get_default_partition_content_name(partition_id partitionID, // do one digit precision. uint64 result = uint64(size * 10 + 0.5); - snprintf(buffer, bufferSize, "%s Volume (%ld.%ld %sB)", fileSystemName, - int32(result / 10), int32(result % 10), suffixes[index]); + snprintf(buffer, bufferSize, "%s Volume (%" B_PRId32 ".%" B_PRId32 " %sB)", + fileSystemName, int32(result / 10), int32(result % 10), suffixes[index]); return B_OK; } diff --git a/src/system/kernel/fs/socket.cpp b/src/system/kernel/fs/socket.cpp index 4a3e416c4c..2aca98763b 100644 --- a/src/system/kernel/fs/socket.cpp +++ b/src/system/kernel/fs/socket.cpp @@ -243,7 +243,7 @@ socket_write(struct file_descriptor *descriptor, off_t pos, const void *buffer, static status_t -socket_ioctl(struct file_descriptor *descriptor, uint32 op, void *buffer, +socket_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer, size_t length) { return sStackInterface->ioctl(descriptor->u.socket, op, buffer, length); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6737a3046c..d2a5e768f3 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -320,7 +320,7 @@ static status_t query_rewind(struct file_descriptor* descriptor); static void query_free_fd(struct file_descriptor* descriptor); static status_t query_close(struct file_descriptor* descriptor); -static status_t common_ioctl(struct file_descriptor* descriptor, uint32 op, +static status_t common_ioctl(struct file_descriptor* descriptor, ulong op, void* buffer, size_t length); static status_t common_read_stat(struct file_descriptor* descriptor, struct stat* statData); @@ -1135,8 +1135,8 @@ restart: rw_lock_read_unlock(&sVnodeLock); if (!canWait || --tries < 0) { // vnode doesn't seem to become unbusy - dprintf("vnode %ld:%Ld is not becoming unbusy!\n", mountID, - vnodeID); + dprintf("vnode %" B_PRIdDEV ":%" B_PRIdINO " is not becoming unbusy!\n", + mountID, vnodeID); return B_BUSY; } snooze(5000); // 5 ms @@ -1930,8 +1930,8 @@ get_root_vnode(bool kernel) return root; // That should never happen. - dprintf("get_root_vnode(): IO context for team %ld doesn't have a " - "root\n", team_get_current_team_id()); + dprintf("get_root_vnode(): IO context for team %" B_PRId32 " doesn't " + "have a root\n", team_get_current_team_id()); } inc_vnode_ref_count(sRoot); @@ -2088,8 +2088,8 @@ lookup_dir_entry(struct vnode* dir, const char* name, struct vnode** _vnode) rw_lock_read_unlock(&sVnodeLock); if (*_vnode == NULL) { - panic("lookup_dir_entry(): could not lookup vnode (mountid 0x%lx vnid " - "0x%Lx)\n", dir->device, id); + panic("lookup_dir_entry(): could not lookup vnode (mountid 0x%" B_PRIx32 + " vnid 0x%" B_PRIx64 ")\n", dir->device, id); return B_ENTRY_NOT_FOUND; } @@ -2952,17 +2952,17 @@ _dump_advisory_locking(advisory_locking* locking) if (locking == NULL) return; - kprintf(" lock: %ld", locking->lock); - kprintf(" wait_sem: %ld", locking->wait_sem); + kprintf(" lock: %" B_PRId32, locking->lock); + kprintf(" wait_sem: %" B_PRId32, locking->wait_sem); int32 index = 0; LockList::Iterator iterator = locking->locks.GetIterator(); while (iterator.HasNext()) { struct advisory_lock* lock = iterator.Next(); - kprintf(" [%2ld] team: %ld\n", index++, lock->team); - kprintf(" start: %Ld\n", lock->start); - kprintf(" end: %Ld\n", lock->end); + kprintf(" [%2" B_PRId32 "] team: %" B_PRId32 "\n", index++, lock->team); + kprintf(" start: %" B_PRIdOFF "\n", lock->start); + kprintf(" end: %" B_PRIdOFF "\n", lock->end); kprintf(" shared? %s\n", lock->shared ? "yes" : "no"); } } @@ -2972,7 +2972,7 @@ static void _dump_mount(struct fs_mount* mount) { kprintf("MOUNT: %p\n", mount); - kprintf(" id: %ld\n", mount->id); + kprintf(" id: %" B_PRIdDEV "\n", mount->id); kprintf(" device_name: %s\n", mount->device_name); kprintf(" root_vnode: %p\n", mount->root_vnode); kprintf(" covers: %p\n", mount->root_vnode->covers); @@ -2984,7 +2984,7 @@ _dump_mount(struct fs_mount* mount) fs_volume* volume = mount->volume; while (volume != NULL) { kprintf(" volume %p:\n", volume); - kprintf(" layer: %ld\n", volume->layer); + kprintf(" layer: %" B_PRId32 "\n", volume->layer); kprintf(" private_volume: %p\n", volume->private_volume); kprintf(" ops: %p\n", volume->ops); kprintf(" file_system: %p\n", volume->file_system); @@ -3098,9 +3098,9 @@ static void _dump_vnode(struct vnode* vnode, bool printPath) { kprintf("VNODE: %p\n", vnode); - kprintf(" device: %ld\n", vnode->device); - kprintf(" id: %Ld\n", vnode->id); - kprintf(" ref_count: %ld\n", vnode->ref_count); + kprintf(" device: %" B_PRIdDEV "\n", vnode->device); + kprintf(" id: %" B_PRIdINO "\n", vnode->id); + kprintf(" ref_count: %" B_PRId32 "\n", vnode->ref_count); kprintf(" private_node: %p\n", vnode->private_node); kprintf(" mount: %p\n", vnode->mount); kprintf(" covered_by: %p\n", vnode->covered_by); @@ -3149,16 +3149,16 @@ dump_mount(int argc, char** argv) return 0; } - uint32 id = parse_expression(argv[1]); - struct fs_mount* mount = NULL; + ulong val = parse_expression(argv[1]); + uint32 id = val; - mount = (fs_mount*)hash_lookup(sMountsTable, (void*)&id); + struct fs_mount* mount = (fs_mount*)hash_lookup(sMountsTable, (void*)&id); if (mount == NULL) { if (IS_USER_ADDRESS(id)) { kprintf("fs_mount not found\n"); return 0; } - mount = (fs_mount*)id; + mount = (fs_mount*)val; } _dump_mount(mount); @@ -3182,7 +3182,7 @@ dump_mounts(int argc, char** argv) hash_open(sMountsTable, &iterator); while ((mount = (struct fs_mount*)hash_next(sMountsTable, &iterator)) != NULL) { - kprintf("%p%4ld %p %p %p %s\n", mount, mount->id, mount->root_vnode, + kprintf("%p%4" B_PRIdDEV " %p %p %p %s\n", mount, mount->id, mount->root_vnode, mount->root_vnode->covers, mount->volume->private_volume, mount->volume->file_system_name); @@ -3265,10 +3265,11 @@ dump_vnodes(int argc, char** argv) if (vnode->device != device) continue; - kprintf("%p%4ld%10Ld%5ld %p %p %p %s%s%s\n", vnode, vnode->device, - vnode->id, vnode->ref_count, vnode->cache, vnode->private_node, - vnode->advisory_locking, vnode->IsRemoved() ? "r" : "-", - vnode->IsBusy() ? "b" : "-", vnode->IsUnpublished() ? "u" : "-"); + kprintf("%p%4" B_PRIdDEV "%10" B_PRIdINO "%5" B_PRId32 " %p %p %p %s%s%s\n", + vnode, vnode->device, vnode->id, vnode->ref_count, vnode->cache, + vnode->private_node, vnode->advisory_locking, + vnode->IsRemoved() ? "r" : "-", vnode->IsBusy() ? "b" : "-", + vnode->IsUnpublished() ? "u" : "-"); } hash_close(sVnodeTable, &iterator, false); @@ -3301,9 +3302,10 @@ dump_vnode_caches(int argc, char** argv) if (device != -1 && vnode->device != device) continue; - kprintf("%p%4ld%10Ld %p %8Ld%8ld\n", vnode, vnode->device, vnode->id, - vnode->cache, (vnode->cache->virtual_end + B_PAGE_SIZE - 1) - / B_PAGE_SIZE, vnode->cache->page_count); + kprintf("%p%4" B_PRIdDEV "%10" B_PRIdINO " %p %8" B_PRIdOFF "%8" B_PRId32 "\n", + vnode, vnode->device, vnode->id, vnode->cache, + (vnode->cache->virtual_end + B_PAGE_SIZE - 1) / B_PAGE_SIZE, + vnode->cache->page_count); } hash_close(sVnodeTable, &iterator, false); @@ -3322,13 +3324,13 @@ dump_io_context(int argc, char** argv) struct io_context* context = NULL; if (argc > 1) { - uint32 num = parse_expression(argv[1]); + ulong num = parse_expression(argv[1]); if (IS_KERNEL_ADDRESS(num)) context = (struct io_context*)num; else { Team* team = team_get_team_struct_locked(num); if (team == NULL) { - kprintf("could not find team with ID %ld\n", num); + kprintf("could not find team with ID %lu\n", num); return 0; } context = (struct io_context*)team->io_context; @@ -3339,8 +3341,8 @@ dump_io_context(int argc, char** argv) kprintf("I/O CONTEXT: %p\n", context); kprintf(" root vnode:\t%p\n", context->root); kprintf(" cwd vnode:\t%p\n", context->cwd); - kprintf(" used fds:\t%lu\n", context->num_used_fds); - kprintf(" max fds:\t%lu\n", context->table_size); + kprintf(" used fds:\t%" B_PRIu32 "\n", context->num_used_fds); + kprintf(" max fds:\t%" B_PRIu32 "\n", context->table_size); if (context->num_used_fds) kprintf(" no. type ops ref open mode pos" @@ -3360,8 +3362,8 @@ dump_io_context(int argc, char** argv) fd->u.vnode); } - kprintf(" used monitors:\t%lu\n", context->num_monitors); - kprintf(" max monitors:\t%lu\n", context->max_monitors); + kprintf(" used monitors:\t%" B_PRIu32 "\n", context->num_monitors); + kprintf(" max monitors:\t%" B_PRIu32 "\n", context->max_monitors); set_debug_variable("_cwd", (addr_t)context->cwd); @@ -3377,8 +3379,8 @@ dump_vnode_usage(int argc, char** argv) return 0; } - kprintf("Unused vnodes: %ld (max unused %ld)\n", sUnusedVnodes, - kMaxUnusedVnodes); + kprintf("Unused vnodes: %" B_PRIu32 " (max unused %" B_PRIu32 ")\n", + sUnusedVnodes, kMaxUnusedVnodes); struct hash_iterator iterator; hash_open(sVnodeTable, &iterator); @@ -3391,7 +3393,8 @@ dump_vnode_usage(int argc, char** argv) hash_close(sVnodeTable, &iterator, false); - kprintf("%lu vnodes total (%ld in use).\n", count, count - sUnusedVnodes); + kprintf("%" B_PRIu32 " vnodes total (%" B_PRIu32 " in use).\n", count, + count - sUnusedVnodes); return 0; } @@ -3449,7 +3452,7 @@ common_file_io_vec_pages(struct vnode* vnode, void* cookie, // now directly read the data from the device // the first file_io_vec can be read directly - if (fileVecs[0].length < numBytes) + if (fileVecs[0].length < (off_t)numBytes) size = fileVecs[0].length; else size = numBytes; @@ -3469,20 +3472,20 @@ common_file_io_vec_pages(struct vnode* vnode, void* cookie, // a) also use this direct I/O for writes (otherwise, it would // overwrite precious data) // b) panic if the term below is true (at least for writes) - if (size > fileVecs[0].length) { + if ((off_t)size > fileVecs[0].length) { //dprintf("warning: device driver %p doesn't respect total length " // "in read_pages() call!\n", ref->device); size = fileVecs[0].length; } - ASSERT(size <= fileVecs[0].length); + ASSERT((off_t)size <= fileVecs[0].length); // If the file portion was contiguous, we're already done now if (size == numBytes) return B_OK; // if we reached the end of the file, we can return as well - if (size != fileVecs[0].length) { + if ((off_t)size != fileVecs[0].length) { *_numBytes = size; return B_OK; } @@ -3525,7 +3528,7 @@ common_file_io_vec_pages(struct vnode* vnode, void* cookie, size = 0; // assign what is left of the current fileVec to the tempVecs - for (size = 0; size < fileLeft && vecIndex < vecCount + for (size = 0; (off_t)size < fileLeft && vecIndex < vecCount && tempCount < MAX_TEMP_IO_VECS;) { // try to satisfy one iovec per iteration (or as much as // possible) @@ -3622,8 +3625,9 @@ new_vnode(fs_volume* volume, ino_t vnodeID, void* privateNode, // file system integrity check: // test if the vnode already exists and bail out if this is the case! if (!nodeCreated) { - panic("vnode %ld:%Ld already exists (node = %p, vnode->node = %p)!", - volume->id, vnodeID, privateNode, vnode->private_node); + panic("vnode %" B_PRIdDEV ":%" B_PRIdINO " already exists (node = %p, " + "vnode->node = %p)!", volume->id, vnodeID, privateNode, + vnode->private_node); return B_ERROR; } @@ -5275,7 +5279,7 @@ create_vnode(struct vnode* directory, const char* name, int openMode, if (vnode == NULL) { panic("vfs: fs_create() returned success but there is no vnode, " - "mount ID %ld!\n", directory->device); + "mount ID %" B_PRIdDEV "!\n", directory->device); return B_BAD_VALUE; } @@ -5895,7 +5899,7 @@ dir_remove(int fd, char* path, bool kernel) static status_t -common_ioctl(struct file_descriptor* descriptor, uint32 op, void* buffer, +common_ioctl(struct file_descriptor* descriptor, ulong op, void* buffer, size_t length) { struct vnode* vnode = descriptor->u.vnode; @@ -5925,9 +5929,10 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) status_t status = B_OK; if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) { + // TODO: x86_64 needs ulong argument here. if (descriptor->type != FDTYPE_FILE) status = B_BAD_VALUE; - else if (user_memcpy(&flock, (struct flock*)argument, + else if (user_memcpy(&flock, (struct flock*)((ulong)argument), sizeof(struct flock)) != B_OK) status = B_BAD_ADDRESS; @@ -6009,7 +6014,8 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) status = get_advisory_lock(vnode, &flock); if (status == B_OK) { // copy back flock structure - status = user_memcpy((struct flock*)argument, &flock, + // TODO: x86_64 + status = user_memcpy((struct flock*)((ulong)argument), &flock, sizeof(struct flock)); } } else @@ -7924,7 +7930,7 @@ _kern_sync(void) while ((device = next_dev(&cookie)) >= 0) { status_t status = fs_sync(device); if (status != B_OK && status != B_BAD_VALUE) { - dprintf("sync: device %ld couldn't sync: %s\n", device, + dprintf("sync: device %" B_PRIdDEV " couldn't sync: %s\n", device, strerror(status)); } } @@ -9216,8 +9222,8 @@ _user_create_pipe(int* userFDs) status = get_vnode(sRoot->mount->id, nodeID, &vnode, true, false); if (status != B_OK) { // that should not happen - dprintf("_user_create_pipe(): Failed to lookup vnode (%ld, %lld)\n", - sRoot->mount->id, sRoot->id); + dprintf("_user_create_pipe(): Failed to lookup vnode (%" B_PRIdDEV ", " + "%" B_PRIdINO ")\n", sRoot->mount->id, sRoot->id); return status; } diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index 7d4feecc76..0c0aba4154 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -329,7 +329,8 @@ get_boot_partitions(kernel_args* args, PartitionStack& partitions) // create boot method int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); - dprintf("get_boot_partitions(): boot method type: %ld\n", bootMethodType); + dprintf("get_boot_partitions(): boot method type: %" B_PRId32 "\n", + bootMethodType); BootMethod* bootMethod = NULL; switch (bootMethodType) { diff --git a/src/system/kernel/fs/vfs_request_io.cpp b/src/system/kernel/fs/vfs_request_io.cpp index 677c554ac0..afa5b0659b 100644 --- a/src/system/kernel/fs/vfs_request_io.cpp +++ b/src/system/kernel/fs/vfs_request_io.cpp @@ -140,7 +140,7 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request, TRACE_RIO("[%ld] do_iterative_fd_io_iterate(request: %p)\n", find_thread(NULL), request); - static const int32 kMaxSubRequests = 8; + static const size_t kMaxSubRequests = 8; iterative_io_cookie* cookie = (iterative_io_cookie*)_cookie; @@ -152,7 +152,7 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request, // get the next file vecs file_io_vec vecs[kMaxSubRequests]; - uint32 vecCount = kMaxSubRequests; + size_t vecCount = kMaxSubRequests; status_t error = cookie->get_vecs(cookie->cookie, request, requestOffset, requestLength, vecs, &vecCount); if (error != B_OK && error != B_BUFFER_OVERFLOW) @@ -161,11 +161,11 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request, *_partialTransfer = true; return B_OK; } - TRACE_RIO("[%ld] got %lu file vecs\n", find_thread(NULL), vecCount); + TRACE_RIO("[%ld] got %zu file vecs\n", find_thread(NULL), vecCount); // create subrequests for the file vecs we've got - int32 subRequestCount = 0; - for (uint32 i = 0; i < vecCount && subRequestCount < kMaxSubRequests; i++) { + size_t subRequestCount = 0; + for (size_t i = 0; i < vecCount && subRequestCount < kMaxSubRequests; i++) { off_t vecOffset = vecs[i].offset; off_t vecLength = min_c(vecs[i].length, requestLength); TRACE_RIO("[%ld] vec %lu offset: %lld, length: %lld\n", @@ -270,13 +270,13 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie, while (error == B_OK && vecLength > 0) { file_io_vec fileVecs[8]; - uint32 fileVecCount = 8; + size_t fileVecCount = 8; error = getVecs(cookie, request, offset, vecLength, fileVecs, &fileVecCount); if (error != B_OK || fileVecCount == 0) break; - for (uint32 i = 0; i < fileVecCount; i++) { + for (size_t i = 0; i < fileVecCount; i++) { const file_io_vec& fileVec = fileVecs[i]; size_t toTransfer = min_c(fileVec.length, (off_t)length); size_t transferred = toTransfer; diff --git a/src/system/kernel/lib/arch/x86_64/arch_string.cpp b/src/system/kernel/lib/arch/x86_64/arch_string.cpp index 0c7e8a79c7..a3d6c8b8a4 100644 --- a/src/system/kernel/lib/arch/x86_64/arch_string.cpp +++ b/src/system/kernel/lib/arch/x86_64/arch_string.cpp @@ -12,8 +12,8 @@ void * memcpy(void *dest, const void *src, size_t count) { - const unsigned char *s = src; - unsigned char *d = dest; + const unsigned char *s = reinterpret_cast(src); + unsigned char *d = reinterpret_cast(dest); for (; count != 0; count--) { *d++ = *s++; @@ -26,7 +26,7 @@ memcpy(void *dest, const void *src, size_t count) void * memset(void *dest, int val, size_t count) { - unsigned char *d = dest; + unsigned char *d = reinterpret_cast(dest); for (; count != 0; count--) { *d++ = static_cast(val); diff --git a/src/system/kernel/lib/kernel_vsprintf.cpp b/src/system/kernel/lib/kernel_vsprintf.cpp index 84c14109bb..5fbad19693 100644 --- a/src/system/kernel/lib/kernel_vsprintf.cpp +++ b/src/system/kernel/lib/kernel_vsprintf.cpp @@ -407,7 +407,7 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) } outBuffer.PutString("0x", 2); - number(outBuffer, (uint32)va_arg(args, void *), 16, fieldWidth, + number(outBuffer, (addr_t)va_arg(args, void *), 16, fieldWidth, precision, flags); continue; diff --git a/src/system/kernel/locks/lock.cpp b/src/system/kernel/locks/lock.cpp index 1cc5c358cf..fda4d321b6 100644 --- a/src/system/kernel/locks/lock.cpp +++ b/src/system/kernel/locks/lock.cpp @@ -535,17 +535,17 @@ dump_rw_lock_info(int argc, char** argv) kprintf("rw lock %p:\n", lock); kprintf(" name: %s\n", lock->name); - kprintf(" holder: %ld\n", lock->holder); - kprintf(" count: %#lx\n", lock->count); + kprintf(" holder: %" B_PRId32 "\n", lock->holder); + kprintf(" count: %#" B_PRIx32 "\n", lock->count); kprintf(" active readers %d\n", lock->active_readers); kprintf(" pending readers %d\n", lock->pending_readers); - kprintf(" owner count: %#lx\n", lock->owner_count); - kprintf(" flags: %#lx\n", lock->flags); + kprintf(" owner count: %#" B_PRIx32 "\n", lock->owner_count); + kprintf(" flags: %#" B_PRIx32 "\n", lock->flags); kprintf(" waiting threads:"); rw_lock_waiter* waiter = lock->waiters; while (waiter != NULL) { - kprintf(" %ld/%c", waiter->thread->id, waiter->writer ? 'w' : 'r'); + kprintf(" %" B_PRId32 "/%c", waiter->thread->id, waiter->writer ? 'w' : 'r'); waiter = waiter->next; } kputs("\n"); @@ -679,7 +679,7 @@ _mutex_lock(mutex* lock, bool schedulerLocked) lock->holder = thread_get_current_thread_id(); return B_OK; } else if (lock->holder == thread_get_current_thread_id()) { - panic("_mutex_lock(): double lock of %p by thread %ld", lock, + panic("_mutex_lock(): double lock of %p by thread %" B_PRId32, lock, lock->holder); } else if (lock->holder == 0) panic("_mutex_lock(): using unitialized lock %p", lock); @@ -723,9 +723,9 @@ _mutex_unlock(mutex* lock, bool schedulerLocked) #if KDEBUG if (thread_get_current_thread_id() != lock->holder) { - panic("_mutex_unlock() failure: thread %ld is trying to release " - "mutex %p (current holder %ld)\n", thread_get_current_thread_id(), - lock, lock->holder); + panic("_mutex_unlock() failure: thread %" B_PRId32 " is trying to " + "release mutex %p (current holder %" B_PRId32 ")\n", + thread_get_current_thread_id(), lock, lock->holder); return; } #else @@ -798,7 +798,7 @@ _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout) lock->holder = thread_get_current_thread_id(); return B_OK; } else if (lock->holder == thread_get_current_thread_id()) { - panic("_mutex_lock(): double lock of %p by thread %ld", lock, + panic("_mutex_lock(): double lock of %p by thread %" B_PRId32, lock, lock->holder); } else if (lock->holder == 0) panic("_mutex_lock(): using unitialized lock %p", lock); @@ -889,7 +889,7 @@ dump_mutex_info(int argc, char** argv) kprintf(" name: %s\n", lock->name); kprintf(" flags: 0x%x\n", lock->flags); #if KDEBUG - kprintf(" holder: %ld\n", lock->holder); + kprintf(" holder: %" B_PRId32 "\n", lock->holder); #else kprintf(" count: %ld\n", lock->count); #endif @@ -897,7 +897,7 @@ dump_mutex_info(int argc, char** argv) kprintf(" waiting threads:"); mutex_waiter* waiter = lock->waiters; while (waiter != NULL) { - kprintf(" %ld", waiter->thread->id); + kprintf(" %" B_PRId32, waiter->thread->id); waiter = waiter->next; } kputs("\n"); diff --git a/src/system/kernel/posix/xsi_message_queue.cpp b/src/system/kernel/posix/xsi_message_queue.cpp index 67386657fb..278c241f67 100644 --- a/src/system/kernel/posix/xsi_message_queue.cpp +++ b/src/system/kernel/posix/xsi_message_queue.cpp @@ -775,8 +775,9 @@ _user_xsi_msgrcv(int messageQueueID, void *messagePointer, messageQueue = sMessageQueueHashTable.Lookup(messageQueueID); if (result == EIDRM || messageQueue == NULL || (messageQueue != NULL && sequenceNumber != messageQueue->SequenceNumber())) { - TRACE_ERROR(("xsi_msgrcv: message queue id %d (sequence = %ld) " - "got destroyed\n", messageQueueID, sequenceNumber)); + TRACE_ERROR(("xsi_msgrcv: message queue id %d (sequence = " + "%" B_PRIu32 ") got destroyed\n", messageQueueID, + sequenceNumber)); return EIDRM; } else if (result == B_INTERRUPTED) { TRACE_ERROR(("xsi_msgrcv: thread %d got interrupted while " @@ -881,8 +882,9 @@ _user_xsi_msgsnd(int messageQueueID, const void *messagePointer, messageQueue = sMessageQueueHashTable.Lookup(messageQueueID); if (result == EIDRM || messageQueue == NULL || (messageQueue != NULL && sequenceNumber != messageQueue->SequenceNumber())) { - TRACE_ERROR(("xsi_msgsnd: message queue id %d (sequence = %ld) " - "got destroyed\n", messageQueueID, sequenceNumber)); + TRACE_ERROR(("xsi_msgsnd: message queue id %d (sequence = " + "%" B_PRIu32 ") got destroyed\n", messageQueueID, + sequenceNumber)); delete message; notSent = false; result = EIDRM; diff --git a/src/system/kernel/posix/xsi_semaphore.cpp b/src/system/kernel/posix/xsi_semaphore.cpp index 161479c85a..212ee1b592 100644 --- a/src/system/kernel/posix/xsi_semaphore.cpp +++ b/src/system/kernel/posix/xsi_semaphore.cpp @@ -1117,7 +1117,8 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps) for (; i < numOps; i++) { short semaphoreNumber = operations[i].sem_num; if (semaphoreNumber >= numberOfSemaphores) { - TRACE_ERROR(("xsi_semop: %ld invalid semaphore number\n", i)); + TRACE_ERROR(("xsi_semop: %" B_PRIu32 " invalid semaphore number" + "\n", i)); result = EINVAL; break; } @@ -1188,8 +1189,9 @@ _user_xsi_semop(int semaphoreID, struct sembuf *ops, size_t numOps) semaphoreSet = sSemaphoreHashTable.Lookup(semaphoreID); if (result == EIDRM || semaphoreSet == NULL || (semaphoreSet != NULL && sequenceNumber != semaphoreSet->SequenceNumber())) { - TRACE_ERROR(("xsi_semop: semaphore set id %d (sequence = %ld) " - "got destroyed\n", semaphoreID, sequenceNumber)); + TRACE_ERROR(("xsi_semop: semaphore set id %d (sequence = " + "%" B_PRIu32 ") got destroyed\n", semaphoreID, + sequenceNumber)); notDone = false; result = EIDRM; } else if (result == B_INTERRUPTED) { diff --git a/src/system/kernel/scheduler/scheduler.cpp b/src/system/kernel/scheduler/scheduler.cpp index 0d571d67dd..e4848d1d48 100644 --- a/src/system/kernel/scheduler/scheduler.cpp +++ b/src/system/kernel/scheduler/scheduler.cpp @@ -64,7 +64,7 @@ void scheduler_init(void) { int32 cpuCount = smp_get_num_cpus(); - dprintf("scheduler_init: found %ld logical cpu%s\n", cpuCount, + dprintf("scheduler_init: found %" B_PRId32 " logical cpu%s\n", cpuCount, cpuCount != 1 ? "s" : ""); if (cpuCount > 1) { diff --git a/src/system/kernel/scheduler/scheduler_affine.cpp b/src/system/kernel/scheduler/scheduler_affine.cpp index 6045e15f7a..10fa82ce5a 100644 --- a/src/system/kernel/scheduler/scheduler_affine.cpp +++ b/src/system/kernel/scheduler/scheduler_affine.cpp @@ -109,13 +109,13 @@ dump_run_queue(int argc, char **argv) for (int32 i = 0; i < smp_get_num_cpus(); i++) { thread = sRunQueue[i]; - kprintf("Run queue for cpu %ld (%ld threads)\n", i, + kprintf("Run queue for cpu %" B_PRId32 " (%" B_PRId32 " threads)\n", i, sRunQueueSize[i]); if (sRunQueueSize[i] > 0) { kprintf("thread id priority avg. quantum name\n"); while (thread) { - kprintf("%p %-7ld %-8ld %-12ld %s\n", thread, thread->id, - thread->priority, + kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %-12" B_PRId32 + " %s\n", thread, thread->id, thread->priority, thread->scheduler_data->GetAverageQuantumUsage(), thread->name); thread = thread->queue_next; diff --git a/src/system/kernel/scheduler/scheduler_simple.cpp b/src/system/kernel/scheduler/scheduler_simple.cpp index 4898781cdf..a68a1c3a47 100644 --- a/src/system/kernel/scheduler/scheduler_simple.cpp +++ b/src/system/kernel/scheduler/scheduler_simple.cpp @@ -67,8 +67,8 @@ dump_run_queue(int argc, char **argv) else { kprintf("thread id priority name\n"); while (thread) { - kprintf("%p %-7ld %-8ld %s\n", thread, thread->id, - thread->priority, thread->name); + kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %s\n", thread, + thread->id, thread->priority, thread->name); thread = thread->queue_next; } } diff --git a/src/system/kernel/scheduler/scheduler_simple_smp.cpp b/src/system/kernel/scheduler/scheduler_simple_smp.cpp index 32dd4e2d59..7ca4d7f598 100644 --- a/src/system/kernel/scheduler/scheduler_simple_smp.cpp +++ b/src/system/kernel/scheduler/scheduler_simple_smp.cpp @@ -70,8 +70,8 @@ dump_run_queue(int argc, char **argv) else { kprintf("thread id priority name\n"); while (thread) { - kprintf("%p %-7ld %-8ld %s\n", thread, thread->id, - thread->priority, thread->name); + kprintf("%p %-7" B_PRId32 " %-8" B_PRId32 " %s\n", thread, + thread->id, thread->priority, thread->name); thread = thread->queue_next; } } diff --git a/src/system/kernel/slab/MemoryManager.cpp b/src/system/kernel/slab/MemoryManager.cpp index 3a6ac26f55..f21d5ed392 100644 --- a/src/system/kernel/slab/MemoryManager.cpp +++ b/src/system/kernel/slab/MemoryManager.cpp @@ -2041,7 +2041,7 @@ MemoryManager::_DumpAreas(int argc, char** argv) kprintf(" medium: %" B_PRIuSIZE "/%" B_PRIuSIZE "\n", totalUsedMedium, totalTotalMedium); kprintf(" large: %" B_PRIuSIZE "\n", totalUsedLarge); - kprintf(" memory: %" B_PRIuSIZE "/%" B_PRIuSIZE " KB\n", + kprintf(" memory: %" B_PRIuSIZE "/%" B_PRIu32 " KB\n", (totalUsedSmall * SLAB_CHUNK_SIZE_SMALL + totalUsedMedium * SLAB_CHUNK_SIZE_MEDIUM + totalUsedLarge * SLAB_CHUNK_SIZE_LARGE) / 1024, diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index 8f9bdbe0be..327506ae73 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -266,8 +266,8 @@ dump_slabs(int argc, char* argv[]) while (it.HasNext()) { ObjectCache* cache = it.Next(); - kprintf("%p %22s %8lu %8" B_PRIuSIZE " %8lu %6lu %8lu %8lu %8lx\n", - cache, cache->name, cache->object_size, cache->alignment, + kprintf("%p %22s %8lu %8" B_PRIuSIZE " %8lu %6lu %8lu %8lu %8" B_PRIx32 + "\n", cache, cache->name, cache->object_size, cache->alignment, cache->usage, cache->empty_count, cache->used_count, cache->total_objects, cache->flags); } @@ -298,7 +298,7 @@ dump_cache_info(int argc, char* argv[]) kprintf("slab_size: %lu\n", cache->slab_size); kprintf("usage: %lu\n", cache->usage); kprintf("maximum: %lu\n", cache->maximum); - kprintf("flags: 0x%lx\n", cache->flags); + kprintf("flags: 0x%" B_PRIx32 "\n", cache->flags); kprintf("cookie: %p\n", cache->cookie); kprintf("resize entry don't wait: %p\n", cache->resize_entry_dont_wait); kprintf("resize entry can wait: %p\n", cache->resize_entry_can_wait); diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index b794b07b30..c8ac2cfd5e 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1114,38 +1114,39 @@ static void _dump_team_info(Team* team) { kprintf("TEAM: %p\n", team); - kprintf("id: %ld (%#lx)\n", team->id, team->id); + kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", team->id, + team->id); kprintf("serial_number: %" B_PRId64 "\n", team->serial_number); kprintf("name: '%s'\n", team->Name()); kprintf("args: '%s'\n", team->Args()); kprintf("hash_next: %p\n", team->hash_next); kprintf("parent: %p", team->parent); if (team->parent != NULL) { - kprintf(" (id = %ld)\n", team->parent->id); + kprintf(" (id = %" B_PRId32 ")\n", team->parent->id); } else kprintf("\n"); kprintf("children: %p\n", team->children); kprintf("num_threads: %d\n", team->num_threads); kprintf("state: %d\n", team->state); - kprintf("flags: 0x%lx\n", team->flags); + kprintf("flags: 0x%" B_PRIx32 "\n", team->flags); kprintf("io_context: %p\n", team->io_context); if (team->address_space) kprintf("address_space: %p\n", team->address_space); - kprintf("user data: %p (area %ld)\n", (void*)team->user_data, - team->user_data_area); + kprintf("user data: %p (area %" B_PRId32 ")\n", + (void*)team->user_data, team->user_data_area); kprintf("free user thread: %p\n", team->free_user_threads); kprintf("main_thread: %p\n", team->main_thread); kprintf("thread_list: %p\n", team->thread_list); - kprintf("group_id: %ld\n", team->group_id); - kprintf("session_id: %ld\n", team->session_id); + kprintf("group_id: %" B_PRId32 "\n", team->group_id); + kprintf("session_id: %" B_PRId32 "\n", team->session_id); } static int dump_team_info(int argc, char** argv) { - team_id id = -1; + ulong arg; bool found = false; if (argc < 2) { @@ -1157,10 +1158,10 @@ dump_team_info(int argc, char** argv) return 0; } - id = strtoul(argv[1], NULL, 0); - if (IS_KERNEL_ADDRESS(id)) { + arg = strtoul(argv[1], NULL, 0); + if (IS_KERNEL_ADDRESS(arg)) { // semi-hack - _dump_team_info((Team*)id); + _dump_team_info((Team*)arg); return 0; } @@ -1168,7 +1169,7 @@ dump_team_info(int argc, char** argv) for (TeamTable::Iterator it = sTeamHash.GetIterator(); Team* team = it.Next();) { if ((team->Name() && strcmp(argv[1], team->Name()) == 0) - || team->id == id) { + || team->id == (team_id)arg) { _dump_team_info(team); found = true; break; @@ -1176,7 +1177,7 @@ dump_team_info(int argc, char** argv) } if (!found) - kprintf("team \"%s\" (%ld) doesn't exist!\n", argv[1], id); + kprintf("team \"%s\" (%" B_PRId32 ") doesn't exist!\n", argv[1], (team_id)arg); return 0; } @@ -1188,7 +1189,7 @@ dump_teams(int argc, char** argv) for (TeamTable::Iterator it = sTeamHash.GetIterator(); Team* team = it.Next();) { - kprintf("%p%7ld %p %s\n", team, team->id, team->parent, team->Name()); + kprintf("%p%7" B_PRId32 " %p %s\n", team, team->id, team->parent, team->Name()); } return 0; @@ -2054,7 +2055,7 @@ fork_team(void) if (thread->user_thread == NULL) { #if KDEBUG - panic("user data area not found, parent area is %ld", + panic("user data area not found, parent area is %" B_PRId32, parentTeam->user_data_area); #endif status = B_ERROR; @@ -2237,7 +2238,7 @@ job_control_entry::~job_control_entry() ProcessGroup* group = sGroupHash.Lookup(group_id); if (group == NULL) { panic("job_control_entry::~job_control_entry(): unknown group " - "ID: %ld", group_id); + "ID: %" B_PRId32, group_id); return; } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 6c95268c44..fc5859c5ab 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -365,7 +365,7 @@ Thread::Init(bool idleThread) return error; char temp[64]; - snprintf(temp, sizeof(temp), "thread_%ld_retcode_sem", id); + snprintf(temp, sizeof(temp), "thread_%" B_PRId32 "_retcode_sem", id); exit.sem = create_sem(0, temp); if (exit.sem < 0) return exit.sem; @@ -814,8 +814,8 @@ create_thread_user_stack(Team* team, Thread* thread, void* _stackBase, size_t areaSize = PAGE_ALIGN(stackSize + TLS_SIZE + additionalSize); - snprintf(nameBuffer, B_OS_NAME_LENGTH, "%s_%ld_stack", thread->name, - thread->id); + snprintf(nameBuffer, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_stack", + thread->name, thread->id); virtual_address_restrictions virtualRestrictions = {}; if (thread->id == team->id) { @@ -913,8 +913,8 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) // create the kernel stack char stackName[B_OS_NAME_LENGTH]; - snprintf(stackName, B_OS_NAME_LENGTH, "%s_%ld_kstack", thread->name, - thread->id); + snprintf(stackName, B_OS_NAME_LENGTH, "%s_%" B_PRId32 "_kstack", + thread->name, thread->id); thread->kernel_stack_area = create_area(stackName, (void **)&thread->kernel_stack_base, B_ANY_KERNEL_ADDRESS, KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, @@ -1405,7 +1405,7 @@ make_thread_unreal(int argc, char **argv) if (thread->priority > B_DISPLAY_PRIORITY) { thread->priority = thread->next_priority = B_NORMAL_PRIORITY; - kprintf("thread %ld made unreal\n", thread->id); + kprintf("thread %" B_PRId32 " made unreal\n", thread->id); } } @@ -1441,12 +1441,12 @@ set_thread_prio(int argc, char **argv) if (thread->id != id) continue; thread->priority = thread->next_priority = prio; - kprintf("thread %ld set to priority %ld\n", id, prio); + kprintf("thread %" B_PRId32 " set to priority %" B_PRId32 "\n", id, prio); found = true; break; } if (!found) - kprintf("thread %ld (%#lx) not found\n", id, id); + kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); return 0; } @@ -1474,12 +1474,12 @@ make_thread_suspended(int argc, char **argv) continue; thread->next_state = B_THREAD_SUSPENDED; - kprintf("thread %ld suspended\n", id); + kprintf("thread %" B_PRId32 " suspended\n", id); found = true; break; } if (!found) - kprintf("thread %ld (%#lx) not found\n", id, id); + kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); return 0; } @@ -1507,13 +1507,13 @@ make_thread_resumed(int argc, char **argv) if (thread->state == B_THREAD_SUSPENDED) { scheduler_enqueue_in_run_queue(thread); - kprintf("thread %ld resumed\n", thread->id); + kprintf("thread %" B_PRId32 " resumed\n", thread->id); } found = true; break; } if (!found) - kprintf("thread %ld (%#lx) not found\n", id, id); + kprintf("thread %" B_PRId32 " (%#" B_PRIx32 ") not found\n", id, id); return 0; } @@ -1541,7 +1541,7 @@ drop_into_debugger(int argc, char **argv) if (err) kprintf("drop failed\n"); else - kprintf("thread %ld dropped into user debugger\n", id); + kprintf("thread %" B_PRId32 " dropped into user debugger\n", id); return 0; } @@ -1604,8 +1604,8 @@ static void _dump_thread_info(Thread *thread, bool shortInfo) { if (shortInfo) { - kprintf("%p %6ld %-10s", thread, thread->id, state_to_text(thread, - thread->state)); + kprintf("%p %6" B_PRId32 " %-10s", thread, thread->id, + state_to_text(thread, thread->state)); // does it block on a semaphore or a condition variable? if (thread->state == B_THREAD_WAITING) { @@ -1616,7 +1616,7 @@ _dump_thread_info(Thread *thread, bool shortInfo) if (sem == thread->msg.read_sem) kprintf(" "); else - kprintf("sem %12ld ", sem); + kprintf("sem %12" B_PRId32 " ", sem); break; } @@ -1657,7 +1657,7 @@ _dump_thread_info(Thread *thread, bool shortInfo) else kprintf(" -"); - kprintf("%4ld %p%5ld %s\n", thread->priority, + kprintf("%4" B_PRId32 " %p%5" B_PRId32 " %s\n", thread->priority, (void *)thread->kernel_stack_base, thread->team->id, thread->name != NULL ? thread->name : ""); @@ -1669,13 +1669,15 @@ _dump_thread_info(Thread *thread, bool shortInfo) struct thread_death_entry *death = NULL; kprintf("THREAD: %p\n", thread); - kprintf("id: %ld (%#lx)\n", thread->id, thread->id); + kprintf("id: %" B_PRId32 " (%#" B_PRIx32 ")\n", thread->id, + thread->id); kprintf("serial_number: %" B_PRId64 "\n", thread->serial_number); kprintf("name: \"%s\"\n", thread->name); kprintf("hash_next: %p\nteam_next: %p\nq_next: %p\n", thread->hash_next, thread->team_next, thread->queue_next); - kprintf("priority: %ld (next %ld, I/O: %ld)\n", thread->priority, - thread->next_priority, thread->io_priority); + kprintf("priority: %" B_PRId32 " (next %" B_PRId32 ", " + "I/O: %" B_PRId32 ")\n", thread->priority, thread->next_priority, + thread->io_priority); kprintf("state: %s\n", state_to_text(thread, thread->state)); kprintf("next_state: %s\n", state_to_text(thread, thread->next_state)); kprintf("cpu: %p ", thread->cpu); @@ -1700,7 +1702,7 @@ _dump_thread_info(Thread *thread, bool shortInfo) if (sem == thread->msg.read_sem) kprintf("data\n"); else - kprintf("semaphore %ld\n", sem); + kprintf("semaphore %" B_PRId32 "\n", sem); break; } @@ -1737,17 +1739,18 @@ _dump_thread_info(Thread *thread, bool shortInfo) kprintf("fault_handler: %p\n", (void *)thread->fault_handler); kprintf("team: %p, \"%s\"\n", thread->team, thread->team->Name()); - kprintf(" exit.sem: %ld\n", thread->exit.sem); - kprintf(" exit.status: %#lx (%s)\n", thread->exit.status, strerror(thread->exit.status)); + kprintf(" exit.sem: %" B_PRId32 "\n", thread->exit.sem); + kprintf(" exit.status: %#" B_PRIx32 " (%s)\n", thread->exit.status, + strerror(thread->exit.status)); kprintf(" exit.waiters:\n"); while ((death = (struct thread_death_entry*)list_get_next_item( &thread->exit.waiters, death)) != NULL) { - kprintf("\t%p (thread %ld)\n", death, death->thread); + kprintf("\t%p (thread %" B_PRId32 ")\n", death, death->thread); } - kprintf("kernel_stack_area: %ld\n", thread->kernel_stack_area); + kprintf("kernel_stack_area: %" B_PRId32 "\n", thread->kernel_stack_area); kprintf("kernel_stack_base: %p\n", (void *)thread->kernel_stack_base); - kprintf("user_stack_area: %ld\n", thread->user_stack_area); + kprintf("user_stack_area: %" B_PRId32 "\n", thread->user_stack_area); kprintf("user_stack_base: %p\n", (void *)thread->user_stack_base); kprintf("user_local_storage: %p\n", (void *)thread->user_local_storage); kprintf("user_thread: %p\n", (void *)thread->user_thread); @@ -1755,7 +1758,7 @@ _dump_thread_info(Thread *thread, bool shortInfo) strerror(thread->kernel_errno)); kprintf("kernel_time: %Ld\n", thread->kernel_time); kprintf("user_time: %Ld\n", thread->user_time); - kprintf("flags: 0x%lx\n", thread->flags); + kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); kprintf("architecture dependant section:\n"); arch_thread_dump_info(&thread->arch_info); } @@ -1779,11 +1782,11 @@ dump_thread_info(int argc, char **argv) for (; argi < argc; argi++) { const char *name = argv[argi]; - int32 id = strtoul(name, NULL, 0); + ulong arg = strtoul(name, NULL, 0); - if (IS_KERNEL_ADDRESS(id)) { + if (IS_KERNEL_ADDRESS(arg)) { // semi-hack - _dump_thread_info((Thread *)id, shortInfo); + _dump_thread_info((Thread *)arg, shortInfo); continue; } @@ -1791,7 +1794,7 @@ dump_thread_info(int argc, char **argv) bool found = false; for (ThreadHashTable::Iterator it = sThreadHash.GetIterator(); Thread* thread = it.Next();) { - if (!strcmp(name, thread->name) || thread->id == id) { + if (!strcmp(name, thread->name) || thread->id == (thread_id)arg) { _dump_thread_info(thread, shortInfo); found = true; break; @@ -1799,7 +1802,7 @@ dump_thread_info(int argc, char **argv) } if (!found) - kprintf("thread \"%s\" (%ld) doesn't exist!\n", name, id); + kprintf("thread \"%s\" (%" B_PRId32 ") doesn't exist!\n", name, (thread_id)arg); } return 0; @@ -2527,7 +2530,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, if (status == B_OK) { // this should never happen as the thread deletes the semaphore on exit - panic("could acquire exit_sem for thread %ld\n", id); + panic("could acquire exit_sem for thread %" B_PRId32 "\n", id); } else if (status == B_BAD_SEM_ID) { // this is the way the thread normally exits status = B_OK; @@ -2694,7 +2697,7 @@ thread_init(kernel_args *args) area_info info; char name[64]; - sprintf(name, "idle thread %lu", i + 1); + sprintf(name, "idle thread %" B_PRIu32, i + 1); thread = new(&sIdleThreads[i]) Thread(name, i == 0 ? team_get_kernel_team_id() : -1, &gCPU[i]); if (thread == NULL || thread->Init(true) != B_OK) { @@ -2708,7 +2711,7 @@ thread_init(kernel_args *args) thread->priority = thread->next_priority = B_IDLE_PRIORITY; thread->state = B_THREAD_RUNNING; thread->next_state = B_THREAD_READY; - sprintf(name, "idle thread %lu kstack", i + 1); + sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); thread->kernel_stack_area = find_area(name); if (get_area_info(thread->kernel_stack_area, &info) != B_OK) diff --git a/src/system/kernel/util/khash.cpp b/src/system/kernel/util/khash.cpp index dded1ade73..0bbbffa1a2 100644 --- a/src/system/kernel/util/khash.cpp +++ b/src/system/kernel/util/khash.cpp @@ -417,13 +417,13 @@ hash_dump_table(struct hash_table* table) { uint32 i; - dprintf("hash table %p, table size: %lu, elements: %u\n", table, + dprintf("hash table %p, table size: %" B_PRIu32 ", elements: %u\n", table, table->table_size, table->num_elements); for (i = 0; i < table->table_size; i++) { struct hash_element* element = table->table[i]; if (element != NULL) { - dprintf("%6lu:", i); + dprintf("%6" B_PRIu32 ":", i); while (element != NULL) { dprintf(" %p", element); element = (hash_element*)NEXT(table, element); diff --git a/src/system/kernel/vm/VMAnonymousCache.cpp b/src/system/kernel/vm/VMAnonymousCache.cpp index d9047dfaa8..9f0f834974 100644 --- a/src/system/kernel/vm/VMAnonymousCache.cpp +++ b/src/system/kernel/vm/VMAnonymousCache.cpp @@ -222,8 +222,8 @@ dump_swap_info(int argc, char** argv) for (SwapFileList::Iterator it = sSwapFileList.GetIterator(); swap_file* file = it.Next();) { swap_addr_t total = file->last_slot - file->first_slot; - kprintf(" vnode: %p, pages: total: %lu, free: %lu\n", - file->vnode, total, file->bmp->free_slots); + kprintf(" vnode: %p, pages: total: %" B_PRIu32 ", free: %" B_PRIu32 + "\n", file->vnode, total, file->bmp->free_slots); totalSwapPages += total; freeSwapPages += file->bmp->free_slots; @@ -231,12 +231,12 @@ dump_swap_info(int argc, char** argv) kprintf("\n"); kprintf("swap space in pages:\n"); - kprintf("total: %9lu\n", totalSwapPages); - kprintf("available: %9llu\n", sAvailSwapSpace / B_PAGE_SIZE); - kprintf("reserved: %9llu\n", + kprintf("total: %9" B_PRIu32 "\n", totalSwapPages); + kprintf("available: %9" B_PRIdOFF "\n", sAvailSwapSpace / B_PAGE_SIZE); + kprintf("reserved: %9" B_PRIdOFF "\n", totalSwapPages - sAvailSwapSpace / B_PAGE_SIZE); - kprintf("used: %9lu\n", totalSwapPages - freeSwapPages); - kprintf("free: %9lu\n", freeSwapPages); + kprintf("used: %9" B_PRIu32 "\n", totalSwapPages - freeSwapPages); + kprintf("free: %9" B_PRIu32 "\n", freeSwapPages); return 0; } @@ -303,7 +303,8 @@ find_swap_file(swap_addr_t slotIndex) return swapFile; } - panic("find_swap_file(): can't find swap file for slot %ld\n", slotIndex); + panic("find_swap_file(): can't find swap file for slot %" B_PRIu32 "\n", + slotIndex); return NULL; } diff --git a/src/system/kernel/vm/VMCache.cpp b/src/system/kernel/vm/VMCache.cpp index 9f58c4e0bd..b16ecb54c1 100644 --- a/src/system/kernel/vm/VMCache.cpp +++ b/src/system/kernel/vm/VMCache.cpp @@ -1325,24 +1325,24 @@ void VMCache::Dump(bool showPages) const { kprintf("CACHE %p:\n", this); - kprintf(" ref_count: %ld\n", RefCount()); + kprintf(" ref_count: %" B_PRId32 "\n", RefCount()); kprintf(" source: %p\n", source); kprintf(" type: %s\n", vm_cache_type_to_string(type)); kprintf(" virtual_base: 0x%Lx\n", virtual_base); kprintf(" virtual_end: 0x%Lx\n", virtual_end); - kprintf(" temporary: %ld\n", temporary); + kprintf(" temporary: %" B_PRIu32 "\n", temporary); kprintf(" lock: %p\n", &fLock); #if KDEBUG - kprintf(" lock.holder: %ld\n", fLock.holder); + kprintf(" lock.holder: %" B_PRId32 "\n", fLock.holder); #endif kprintf(" areas:\n"); for (VMArea* area = areas; area != NULL; area = area->cache_next) { - kprintf(" area 0x%lx, %s\n", area->id, area->name); + kprintf(" area 0x%" B_PRIx32 ", %s\n", area->id, area->name); kprintf("\tbase_addr: 0x%lx, size: 0x%lx\n", area->Base(), area->Size()); - kprintf("\tprotection: 0x%lx\n", area->protection); - kprintf("\towner: 0x%lx\n", area->address_space->ID()); + kprintf("\tprotection: 0x%" B_PRIx32 "\n", area->protection); + kprintf("\towner: 0x%" B_PRIx32 "\n", area->address_space->ID()); } kprintf(" consumers:\n"); @@ -1367,7 +1367,7 @@ VMCache::Dump(bool showPages) const } } } else - kprintf("\t%ld in cache\n", page_count); + kprintf("\t%" B_PRIu32 " in cache\n", page_count); } diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp b/src/system/kernel/vm/VMUserAddressSpace.cpp index 11782af2cb..1420e447e5 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.cpp +++ b/src/system/kernel/vm/VMUserAddressSpace.cpp @@ -203,7 +203,8 @@ VMUserAddressSpace::CanResizeArea(VMArea* area, size_t newSize) // also be resized in that area // TODO: if there is free space after the reserved area, it could // be used as well... - return next->id == RESERVED_AREA_ID && next->cache_offset <= area->Base() + return next->id == RESERVED_AREA_ID + && (uint64)next->cache_offset <= (uint64)area->Base() && next->Base() + (next->Size() - 1) >= newEnd; } @@ -218,7 +219,7 @@ VMUserAddressSpace::ResizeArea(VMArea* _area, size_t newSize, VMUserArea* next = fAreas.GetNext(area); if (next != NULL && next->Base() <= newEnd) { if (next->id != RESERVED_AREA_ID - || next->cache_offset > area->Base() + || (uint64)next->cache_offset > (uint64)area->Base() || next->Base() + (next->Size() - 1) < newEnd) { panic("resize situation for area %p has changed although we " "should have the address space lock", area); @@ -361,11 +362,11 @@ VMUserAddressSpace::Dump() const for (VMUserAreaList::ConstIterator it = fAreas.GetIterator(); VMUserArea* area = it.Next();) { - kprintf(" area 0x%lx: ", area->id); + kprintf(" area 0x%" B_PRIx32 ": ", area->id); kprintf("base_addr = 0x%lx ", area->Base()); kprintf("size = 0x%lx ", area->Size()); kprintf("name = '%s' ", area->name); - kprintf("protection = 0x%lx\n", area->protection); + kprintf("protection = 0x%" B_PRIx32 "\n", area->protection); } } diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 857bf22808..27ee5991b8 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -2972,16 +2972,16 @@ display_mem(int argc, char** argv) switch (itemSize) { case 1: - kprintf(" %02x", *(uint8*)&value); + kprintf(" %02" B_PRIx8, *(uint8*)&value); break; case 2: - kprintf(" %04x", *(uint16*)&value); + kprintf(" %04" B_PRIx16, *(uint16*)&value); break; case 4: - kprintf(" %08lx", *(uint32*)&value); + kprintf(" %08" B_PRIx32, *(uint32*)&value); break; case 8: - kprintf(" %016Lx", *(uint64*)&value); + kprintf(" %016" B_PRIx64, *(uint64*)&value); break; } } @@ -3106,9 +3106,9 @@ dump_caches_recursively(VMCache* cache, cache_info& info, int level) for (int i = 0; i < level; i++) kprintf(" "); - kprintf("%p: type: %s, base: %lld, size: %lld, pages: %lu", cache, - vm_cache_type_to_string(cache->type), cache->virtual_base, - cache->virtual_end, cache->page_count); + kprintf("%p: type: %s, base: %" B_PRIdOFF ", size: %" B_PRIdOFF ", " + "pages: %" B_PRIu32, cache, vm_cache_type_to_string(cache->type), + cache->virtual_base, cache->virtual_end, cache->page_count); if (level == 0) kprintf("/%lu", info.page_count); @@ -3123,12 +3123,12 @@ dump_caches_recursively(VMCache* cache, cache_info& info, int level) // areas if (cache->areas != NULL) { VMArea* area = cache->areas; - kprintf(", areas: %ld (%s, team: %ld)", area->id, area->name, - area->address_space->ID()); + kprintf(", areas: %" B_PRId32 " (%s, team: %" B_PRId32 ")", area->id, + area->name, area->address_space->ID()); while (area->cache_next != NULL) { area = area->cache_next; - kprintf(", %ld", area->id); + kprintf(", %" B_PRId32, area->id); } } @@ -3194,9 +3194,9 @@ dump_caches(int argc, char** argv) kprintf("total committed memory: %" B_PRIdOFF ", total used pages: %" B_PRIuPHYSADDR "\n", totalCommitted, totalPages); - kprintf("%lu caches (%lu root caches), sorted by %s per cache " - "tree...\n\n", totalCount, rootCount, - sortByPageCount ? "page count" : "committed size"); + kprintf("%" B_PRIu32 " caches (%" B_PRIu32 " root caches), sorted by %s " + "per cache tree...\n\n", totalCount, rootCount, sortByPageCount ? + "page count" : "committed size"); if (rootCount <= (uint32)kCacheInfoTableCount) { for (uint32 i = 0; i < rootCount; i++) { @@ -3258,11 +3258,11 @@ dump_area_struct(VMArea* area, bool mappings) { kprintf("AREA: %p\n", area); kprintf("name:\t\t'%s'\n", area->name); - kprintf("owner:\t\t0x%lx\n", area->address_space->ID()); - kprintf("id:\t\t0x%lx\n", area->id); + kprintf("owner:\t\t0x%" B_PRIx32 "\n", area->address_space->ID()); + kprintf("id:\t\t0x%" B_PRIx32 "\n", area->id); kprintf("base:\t\t0x%lx\n", area->Base()); kprintf("size:\t\t0x%lx\n", area->Size()); - kprintf("protection:\t0x%lx\n", area->protection); + kprintf("protection:\t0x%" B_PRIx32 "\n", area->protection); kprintf("wiring:\t\t0x%x\n", area->wiring); kprintf("memory_type:\t%#" B_PRIx32 "\n", area->MemoryType()); kprintf("cache:\t\t%p\n", area->cache); @@ -3284,7 +3284,7 @@ dump_area_struct(VMArea* area, bool mappings) while (iterator.Next() != NULL) { count++; } - kprintf("page mappings:\t%lu\n", count); + kprintf("page mappings:\t%" B_PRIu32 "\n", count); } } @@ -3377,9 +3377,9 @@ dump_area_list(int argc, char** argv) || (name != NULL && strstr(area->name, name) == NULL)) continue; - kprintf("%p %5lx %p\t%p %4lx\t%4d %s\n", area, area->id, - (void*)area->Base(), (void*)area->Size(), area->protection, - area->wiring, area->name); + kprintf("%p %5" B_PRIx32 " %p\t%p %4" B_PRIx32 "\t%4d %s\n", area, + area->id, (void*)area->Base(), (void*)area->Size(), + area->protection, area->wiring, area->name); } return 0; } @@ -3852,7 +3852,7 @@ vm_init(kernel_args* args) for (i = 0; i < args->num_cpus; i++) { char name[64]; - sprintf(name, "idle thread %lu kstack", i + 1); + sprintf(name, "idle thread %" B_PRIu32 " kstack", i + 1); address = (void*)args->cpu_kstack[i].start; create_area(name, &address, B_EXACT_ADDRESS, args->cpu_kstack[i].size, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); @@ -4035,7 +4035,7 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, if (status < B_OK) { dprintf("vm_page_fault: vm_soft_fault returned error '%s' on fault at " - "0x%lx, ip 0x%lx, write %d, user %d, thread 0x%lx\n", + "0x%lx, ip 0x%lx, write %d, user %d, thread 0x%" B_PRIx32 "\n", strerror(status), address, faultAddress, isWrite, isUser, thread_get_current_thread_id()); if (!isUser) { @@ -4059,12 +4059,13 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, VMArea* area = addressSpace->LookupArea(faultAddress); Thread* thread = thread_get_current_thread(); - dprintf("vm_page_fault: thread \"%s\" (%ld) in team \"%s\" (%ld) " - "tried to %s address %#lx, ip %#lx (\"%s\" +%#lx)\n", - thread->name, thread->id, thread->team->Name(), - thread->team->id, isWrite ? "write" : "read", address, - faultAddress, area ? area->name : "???", - faultAddress - (area ? area->Base() : 0x0)); + dprintf("vm_page_fault: thread \"%s\" (%" B_PRId32 ") in team " + "\"%s\" (%" B_PRId32 ") tried to %s address %#lx, ip %#lx " + "(\"%s\" +%#lx)\n", thread->name, thread->id, + thread->team->Name(), thread->team->id, + isWrite ? "write" : "read", address, faultAddress, + area ? area->name : "???", faultAddress - (area ? + area->Base() : 0x0)); // We can print a stack trace of the userland thread here. // TODO: The user_memcpy() below can cause a deadlock, if it causes a page @@ -4394,8 +4395,8 @@ vm_soft_fault(VMAddressSpace* addressSpace, addr_t originalAddress, // check permissions uint32 protection = get_area_page_protection(area, address); if (isUser && (protection & B_USER_PROTECTION) == 0) { - dprintf("user access on kernel area 0x%lx at %p\n", area->id, - (void*)originalAddress); + dprintf("user access on kernel area 0x%" B_PRIx32 " at %p\n", + area->id, (void*)originalAddress); TPF(PageFaultError(area->id, VMPageFaultTracing::PAGE_FAULT_ERROR_KERNEL_ONLY)); status = B_PERMISSION_DENIED; @@ -4403,16 +4404,16 @@ vm_soft_fault(VMAddressSpace* addressSpace, addr_t originalAddress, } if (isWrite && (protection & (B_WRITE_AREA | (isUser ? 0 : B_KERNEL_WRITE_AREA))) == 0) { - dprintf("write access attempted on write-protected area 0x%lx at" - " %p\n", area->id, (void*)originalAddress); + dprintf("write access attempted on write-protected area 0x%" + B_PRIx32 " at %p\n", area->id, (void*)originalAddress); TPF(PageFaultError(area->id, VMPageFaultTracing::PAGE_FAULT_ERROR_WRITE_PROTECTED)); status = B_PERMISSION_DENIED; break; } else if (!isWrite && (protection & (B_READ_AREA | (isUser ? 0 : B_KERNEL_READ_AREA))) == 0) { - dprintf("read access attempted on read-protected area 0x%lx at" - " %p\n", area->id, (void*)originalAddress); + dprintf("read access attempted on read-protected area 0x%" B_PRIx32 + " at %p\n", area->id, (void*)originalAddress); TPF(PageFaultError(area->id, VMPageFaultTracing::PAGE_FAULT_ERROR_READ_PROTECTED)); status = B_PERMISSION_DENIED; @@ -4673,7 +4674,7 @@ vm_try_reserve_memory(size_t amount, int priority, bigtime_t timeout) //dprintf("try to reserve %lu bytes, %Lu left\n", amount, sAvailableMemory); - if (sAvailableMemory >= amount + reserve) { + if (sAvailableMemory >= (off_t)(amount + reserve)) { sAvailableMemory -= amount; return B_OK; } @@ -4696,7 +4697,7 @@ vm_try_reserve_memory(size_t amount, int priority, bigtime_t timeout) sNeededMemory -= amount; - if (sAvailableMemory >= amount + reserve) { + if (sAvailableMemory >= (off_t)(amount + reserve)) { sAvailableMemory -= amount; return B_OK; } diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index e7740ddeb6..efedab5827 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -943,8 +943,8 @@ dump_page(int argc, char **argv) && physicalAddress / B_PAGE_SIZE == page->physical_page_number) { VMArea* area = addressSpace->LookupArea(address); - kprintf(" aspace %ld, area %ld: %#" B_PRIxADDR - " (%c%c%s%s)\n", addressSpace->ID(), + kprintf(" aspace %" B_PRId32 ", area %" B_PRId32 ": %#" + B_PRIxADDR " (%c%c%s%s)\n", addressSpace->ID(), area != NULL ? area->id : -1, address, (flags & B_KERNEL_READ_AREA) != 0 ? 'r' : '-', (flags & B_KERNEL_WRITE_AREA) != 0 ? 'w' : '-', @@ -1117,7 +1117,7 @@ dump_page_stats(int argc, char **argv) kprintf("unreserved free pages: %" B_PRId32 "\n", sUnreservedFreePages); kprintf("unsatisfied page reservations: %" B_PRId32 "\n", sUnsatisfiedPageReservations); - kprintf("mapped pages: %lu\n", gMappedPagesCount); + kprintf("mapped pages: %" B_PRId32 "\n", gMappedPagesCount); kprintf("longest free pages run: %" B_PRIuPHYSADDR " pages (at %" B_PRIuPHYSADDR ")\n", longestFreeRun.Length(), sPages[longestFreeRun.start].physical_page_number); diff --git a/src/system/libroot/posix/stdlib/strtod.c b/src/system/libroot/posix/stdlib/strtod.c index 9ff1b400f6..1dc2e54dd3 100644 --- a/src/system/libroot/posix/stdlib/strtod.c +++ b/src/system/libroot/posix/stdlib/strtod.c @@ -126,7 +126,8 @@ #if defined(__i386__) || defined(__ia64__) || defined(__alpha__) || \ defined(__sparc64__) || defined(__powerpc__) || defined(__POWERPC__) || \ defined(__m68k__) || defined(__M68K__) || defined(__arm__) || \ - defined(__ARM__) || defined(__mipsel__) || defined(__MIPSEL__) + defined(__ARM__) || defined(__mipsel__) || defined(__MIPSEL__) || \ + defined(__x86_64__) # include # if BYTE_ORDER == BIG_ENDIAN # define IEEE_BIG_ENDIAN From 82b4b371721bb24f2697b5c17360380cf11aef9c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 16:09:25 +0100 Subject: [PATCH 010/273] Added a TODO in to say that {,u}int64 should be changed to long on x86_64. --- headers/config/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/headers/config/types.h b/headers/config/types.h index f0140a01b9..8da83ecabd 100644 --- a/headers/config/types.h +++ b/headers/config/types.h @@ -22,6 +22,7 @@ typedef signed int __haiku_std_int32; typedef unsigned int __haiku_std_uint32; typedef signed long long __haiku_std_int64; typedef unsigned long long __haiku_std_uint64; + // TODO: on x86_64 these should be long typedef __haiku_std_int8 __haiku_int8; typedef __haiku_std_uint8 __haiku_uint8; From 73f27ecd3a30c16c2363de51891534c09601ea6b Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 19:57:21 +0100 Subject: [PATCH 011/273] Implementations of some libroot functions for x86_64. These are the functions required by the kernel. These are all full implementations except for system_time(), which will be implemented later. --- headers/posix/arch/x86_64/arch_setjmp.h | 5 +- src/system/libroot/os/arch/x86_64/atomic.S | 128 +++++++++++++++ src/system/libroot/os/arch/x86_64/byteorder.S | 54 +++++++ .../libroot/os/arch/x86_64/system_time.c | 4 + .../libroot/os/arch/x86_64/system_time_asm.S | 149 ++++++++++++++++++ .../posix/arch/x86_64/setjmp_internal.h | 20 +++ .../libroot/posix/arch/x86_64/siglongjmp.S | 32 ++++ .../libroot/posix/arch/x86_64/sigsetjmp.S | 39 +++++ 8 files changed, 428 insertions(+), 3 deletions(-) create mode 100644 src/system/libroot/os/arch/x86_64/atomic.S create mode 100644 src/system/libroot/os/arch/x86_64/byteorder.S create mode 100644 src/system/libroot/os/arch/x86_64/system_time.c create mode 100644 src/system/libroot/os/arch/x86_64/system_time_asm.S create mode 100644 src/system/libroot/posix/arch/x86_64/setjmp_internal.h create mode 100644 src/system/libroot/posix/arch/x86_64/siglongjmp.S create mode 100644 src/system/libroot/posix/arch/x86_64/sigsetjmp.S diff --git a/headers/posix/arch/x86_64/arch_setjmp.h b/headers/posix/arch/x86_64/arch_setjmp.h index 3780e9bb78..2d8f39ec4d 100644 --- a/headers/posix/arch/x86_64/arch_setjmp.h +++ b/headers/posix/arch/x86_64/arch_setjmp.h @@ -1,12 +1,11 @@ /* - * Copyright 2005-2010 Haiku Inc. All Rights Reserved. + * Copyright 2005-2012 Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _ARCH_SETJMP_H_ #define _ARCH_SETJMP_H_ -/* TODO: A jmp_buf size of 12 might not be large enough. Increase to a large size if needed. */ -typedef int __jmp_buf[12]; +typedef int __jmp_buf[8]; #endif /* _ARCH_SETJMP_H_ */ diff --git a/src/system/libroot/os/arch/x86_64/atomic.S b/src/system/libroot/os/arch/x86_64/atomic.S new file mode 100644 index 0000000000..7abf2d2743 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/atomic.S @@ -0,0 +1,128 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +.text + +/* int32 atomic_set(vint32 *value, int32 newValue) */ +FUNCTION(atomic_set): + movl %esi, %eax + lock + xchgl %eax, (%rdi) + ret +FUNCTION_END(atomic_set) + +/* int32 atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) */ +FUNCTION(atomic_test_and_set): + movl %edx, %eax + lock + cmpxchgl %esi, (%rdi) + ret +FUNCTION_END(atomic_test_and_set) + +/* int32 atomic_add(vint32 *value, int32 addValue) */ +FUNCTION(atomic_add): + movl %esi, %eax + lock + xaddl %eax, (%rdi) + ret +FUNCTION_END(atomic_add) + +/* int32 atomic_and(vint32 *value, int32 andValue) */ +FUNCTION(atomic_and): + movl (%rdi), %eax +1: movl %eax, %edx + movl %eax, %ecx + andl %esi, %edx + lock + cmpxchgl %edx, (%rdi) + jnz 1b + movl %ecx, %eax + ret +FUNCTION_END(atomic_and) + +/* int32 atomic_or(vint32 *value, int32 orValue) */ +FUNCTION(atomic_or): + movl (%rdi), %eax +1: movl %eax, %edx + movl %eax, %ecx + orl %esi, %edx + lock + cmpxchgl %edx, (%rdi) + jnz 1b + movl %ecx, %eax + ret +FUNCTION_END(atomic_or) + +/* int32 atomic_get(vint32 *value) */ +FUNCTION(atomic_get): + movl (%rdi), %eax +1: lock + cmpxchgl %eax, (%rdi) + jnz 1b + ret +FUNCTION_END(atomic_get) + +/* int64 atomic_set64(vint64 *value, int64 newValue) */ +FUNCTION(atomic_set64): + movq %rsi, %rax + lock + xchgq %rax, (%rdi) + ret +FUNCTION_END(atomic_set64) + +/* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */ +FUNCTION(atomic_test_and_set64): + movq %rdx, %rax + lock + cmpxchgq %rsi, (%rdi) + ret +FUNCTION_END(atomic_test_and_set64) + +/* int64 atomic_add64(vint64 *value, int64 addValue) */ +FUNCTION(atomic_add64): + movq %rsi, %rax + lock + xaddq %rax, (%rdi) + ret +FUNCTION_END(atomic_add64) + +/* int64 atomic_and64(vint64 *value, int64 andValue) */ +FUNCTION(atomic_and64): + movq (%rdi), %rax +1: movq %rax, %rdx + movq %rax, %rcx + andq %rsi, %rdx + lock + cmpxchgq %rdx, (%rdi) + jnz 1b + movq %rcx, %rax + ret +FUNCTION_END(atomic_and64) + +/* int64 atomic_or64(vint64 *value, int64 orValue) */ +FUNCTION(atomic_or64): + movq (%rdi), %rax +1: movq %rax, %rdx + movq %rax, %rcx + orq %rsi, %rdx + lock + cmpxchgq %rdx, (%rdi) + jnz 1b + movq %rcx, %rax + ret +FUNCTION_END(atomic_or64) + +/* int64 atomic_get64(vint64 *value) */ +FUNCTION(atomic_get64): + movq (%rdi), %rax +1: lock + cmpxchgq %rax, (%rdi) + jnz 1b + ret +FUNCTION_END(atomic_get64) diff --git a/src/system/libroot/os/arch/x86_64/byteorder.S b/src/system/libroot/os/arch/x86_64/byteorder.S new file mode 100644 index 0000000000..9b346809fa --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/byteorder.S @@ -0,0 +1,54 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +/* uint16 __swap_int16(uint16 value) */ +FUNCTION(__swap_int16): + movl %edi, %eax + bswap %eax + shr $16, %eax + ret +FUNCTION_END(__swap_int16) + +/* uint32 __swap_int32(uint32 value) */ +FUNCTION(__swap_int32): + movl %edi, %eax + bswap %eax + ret +FUNCTION_END(__swap_int32) + +/* uint64 __swap_int64(uint64 value) */ +FUNCTION(__swap_int64): + movq %rdi, %rax + bswap %rax + ret +FUNCTION_END(__swap_int64) + +/* float __swap_float(float value) */ +FUNCTION(__swap_float): + sub $8, %rsp + movss %xmm0, (%rsp) + movl (%rsp), %eax + bswap %eax + movl %eax, (%rsp) + movss (%rsp), %xmm0 + add $8, %rsp + ret +FUNCTION_END(__swap_float) + +/* double __swap_double(double value) */ +FUNCTION(__swap_double): + sub $8, %rsp + movsd %xmm0, (%rsp) + movq (%rsp), %rax + bswap %rax + movq %rax, (%rsp) + movsd (%rsp), %xmm0 + add $8, %rsp + ret +FUNCTION_END(__swap_double) diff --git a/src/system/libroot/os/arch/x86_64/system_time.c b/src/system/libroot/os/arch/x86_64/system_time.c new file mode 100644 index 0000000000..6b4e3d7df9 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/system_time.c @@ -0,0 +1,4 @@ +/* + Just a dummy to avoid a special case in the build system. system_time() + is implemented in system_time_asm.S. +*/ diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S new file mode 100644 index 0000000000..d6df8fa806 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -0,0 +1,149 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + +#include + +FUNCTION(__x86_setup_system_time): + ret +FUNCTION_END(__x86_setup_system_time) + +// TODO: Implement these. + +/* int64 system_time(); */ +FUNCTION(system_time): + ud2a + ret +FUNCTION_END(system_time) + + +/* int64 system_time_nsecs(); */ +FUNCTION(system_time_nsecs): + ud2a + ret +FUNCTION_END(system_time_nsecs) + +#if 0 +/* saves the conversion factor needed for system_time */ +.lcomm cv_factor 4 +.lcomm cv_factor_nsecs 4 +.lcomm cv_factor_nsecs_shift 1 + + +.text + + +FUNCTION(__x86_setup_system_time): + movl 4(%esp), %eax + movl %eax, cv_factor + movl 8(%esp), %eax + movl %eax, cv_factor_nsecs + movb 12(%esp), %al + movb %al, cv_factor_nsecs_shift + ret +FUNCTION_END(__x86_setup_system_time) + + +/* int64 system_time(); */ +FUNCTION(system_time): + pushl %ebx + pushl %ecx + movl cv_factor, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + + movl %edx, %ecx /* save high half */ + mull %ebx /* truncate %eax, but keep %edx */ + movl %ecx, %eax + movl %edx, %ecx /* save high half of low */ + mull %ebx /*, %eax*/ + /* now compute [%edx, %eax] + [%ecx], propagating carry */ + subl %ebx, %ebx /* need zero to propagate carry */ + addl %ecx, %eax + adc %ebx, %edx + popl %ecx + popl %ebx + ret +FUNCTION_END(system_time) + + +/* int64 system_time_nsecs(); */ +FUNCTION(system_time_nsecs): + testb $0, cv_factor_nsecs_shift + jne 1f + + /* same algorithm as system_time(), just with a different factor */ + + pushl %ebx + pushl %ecx + movl cv_factor_nsecs, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + + movl %edx, %ecx /* save high half */ + mull %ebx /* truncate %eax, but keep %edx */ + movl %ecx, %eax + movl %edx, %ecx /* save high half of low */ + mull %ebx /*, %eax*/ + /* now compute [%edx, %eax] + [%ecx], propagating carry */ + subl %ebx, %ebx /* need zero to propagate carry */ + addl %ecx, %eax + adc %ebx, %edx + popl %ecx + popl %ebx + ret + +1: + /* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */ + + pushl %ebx + pushl %ecx + pushl %esi + movl cv_factor_nsecs, %ebx + + /* load 64-bit factor into %eax (low), %edx (high) */ + rdtsc /* time in %edx,%eax */ + + /* save high half */ + movl %edx, %ecx + + /* multiply low half by conversion factor */ + mull %ebx + + /* save result */ + movl %eax, %esi /* low half -> %esi */ + movl %ecx, %eax + movl %edx, %ecx /* high half -> %ecx */ + + /* multiply high half by conversion factor */ + mull %ebx + + /* now compute [%edx, %eax] + [%ecx], propagating carry */ + xorl %ebx, %ebx /* need zero to propagate carry */ + addl %ecx, %eax + adc %ebx, %edx + + /* shift the result left 16 bit */ + shl $16, %edx + movl %eax, %ebx + shr $16, %ebx + orw %bx, %dx + shl $16, %eax + + /* add the high 16 bit of the low half of the low product */ + shr $16, %esi + orw %si, %ax + + popl %esi + popl %ecx + popl %ebx + ret +FUNCTION_END(system_time_nsecs) +#endif diff --git a/src/system/libroot/posix/arch/x86_64/setjmp_internal.h b/src/system/libroot/posix/arch/x86_64/setjmp_internal.h new file mode 100644 index 0000000000..6d7ed7c56f --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/setjmp_internal.h @@ -0,0 +1,20 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef SETJMP_INTERNAL_H +#define SETJMP_INTERNAL_H + + +#define JMP_REGS_IP 0 +#define JMP_REGS_SP 8 +#define JMP_REGS_BP 16 +#define JMP_REGS_BX 24 +#define JMP_REGS_R12 32 +#define JMP_REGS_R13 40 +#define JMP_REGS_R14 48 +#define JMP_REGS_R15 56 + +#include + +#endif /* SETJMP_INTERNAL_H */ diff --git a/src/system/libroot/posix/arch/x86_64/siglongjmp.S b/src/system/libroot/posix/arch/x86_64/siglongjmp.S new file mode 100644 index 0000000000..5acae0990f --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/siglongjmp.S @@ -0,0 +1,32 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + +#include "setjmp_internal.h" + + +/* int __siglongjmp(jmp_buf buffer, int value) */ +FUNCTION(siglongjmp): +FUNCTION(longjmp): +FUNCTION(_longjmp): + // Restore new callee-save registers. + movq JMP_REGS_R15(%rdi), %r15 + movq JMP_REGS_R14(%rdi), %r14 + movq JMP_REGS_R13(%rdi), %r13 + movq JMP_REGS_R12(%rdi), %r12 + movq JMP_REGS_BX(%rdi), %rbx + movq JMP_REGS_BP(%rdi), %rbp + + // Restore new stack pointer and push return address. + movq JMP_REGS_SP(%rdi), %rsp + movq JMP_REGS_IP(%rdi), %rax + push %rax + + // __longjmp_return restores the signal mask and sets the return value. + call __longjmp_return + ret +FUNCTION_END(siglongjmp) + + +#pragma weak longjmp=siglongjmp diff --git a/src/system/libroot/posix/arch/x86_64/sigsetjmp.S b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S new file mode 100644 index 0000000000..25bef80a68 --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S @@ -0,0 +1,39 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + +#include "setjmp_internal.h" + + +/* int sigsetjmp(jmp_buf buffer, int saveMask) */ +FUNCTION(__sigsetjmp): +FUNCTION(sigsetjmp): + // Save instruction/stack pointers. + movq (%rsp), %rax + movq %rax, JMP_REGS_IP(%rdi) + leaq 8(%rsp), %rax + movq %rax, JMP_REGS_SP(%rdi) + + // Save callee-save registers. + movq %rbp, JMP_REGS_BP(%rdi) + movq %rbx, JMP_REGS_BX(%rdi) + movq %r12, JMP_REGS_R12(%rdi) + movq %r13, JMP_REGS_R13(%rdi) + movq %r14, JMP_REGS_R14(%rdi) + movq %r15, JMP_REGS_R15(%rdi) + + // __setjmp_save_sigs handles signal mask and return value. + jmp __setjmp_save_sigs +FUNCTION_END(setjmp) + + +/* int setjmp(jmp_buf buffer) */ +FUNCTION(setjmp): + // Jump to sigsetjmp with a zero saveMask. + xorl %edi, %edi + jmp sigsetjmp +FUNCTION_END(setjmp) + + +#pragma weak _setjmp=setjmp From 8c0e3c951a108d09b85b57dea3f793dc4eed24d5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 20:05:25 +0100 Subject: [PATCH 012/273] Add -mno-red-zone to the kernel CCFLAGS/C++FLAGS. The red zone is a 128-byte area below the stack pointer specified by the AMD64 ABI that can be used by leaf functions for their stack frame without modifying the stack pointer. It is guaranteed not to be modified by signal handlers. This cannot be used in kernel mode code, as an interrupt handler could overwrite it, so stop GCC from generating code that uses it. --- build/jam/BuildSetup | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 6a564e7ff9..f0f30fbf3c 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -383,9 +383,11 @@ switch $(HAIKU_ARCH) { } case x86_64 : { - # Kernel lives in the top 2GB of the address space, use kernel code model. - HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel ; - HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel ; + # Kernel lives in the top 2GB of the address space, use kernel code + # model. Also disable the red zone, which cannot be used in kernel + # code due to interrupts. + HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel -mno-red-zone ; + HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel -mno-red-zone ; # Bootloader is 32-bit. HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; From 146f966921d878727c3895b18dbee0ab3314bffc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 22:31:24 +0100 Subject: [PATCH 013/273] Fixed a mistake in 11d3892, changed a parameter type to addr_t that shouldn't have been changed. --- src/system/kernel/smp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 6095014f51..bf5f7c7603 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -861,7 +861,7 @@ smp_intercpu_int_handler(int32 cpu) void smp_send_ici(int32 targetCPU, int32 message, addr_t data, addr_t data2, - addr_t data3, void* dataPointer, addr_t flags) + addr_t data3, void* dataPointer, uint32 flags) { struct smp_msg *msg; From 043c61dde5b257e2e094ffb2df82a303d234e5b4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 15 Jun 2012 22:50:59 +0100 Subject: [PATCH 014/273] Added stub versions of everything needed to build the kernel. The whole kernel now builds and there are no undefined references when linking, I just need to fix some strange relocation errors I'm getting (probably a problem with the linker script) and then I'll have a kernel image. --- headers/private/kernel/arch/x86_64/arch_int.h | 2 +- src/system/kernel/arch/x86_64/Jamfile | 14 +++ .../kernel/arch/x86_64/arch_commpage.cpp | 21 ++++ src/system/kernel/arch/x86_64/arch_cpu.cpp | 42 ++++++- src/system/kernel/arch/x86_64/arch_debug.cpp | 102 +++++++++++++++++ .../kernel/arch/x86_64/arch_debug_console.cpp | 91 +++++++++++++++ src/system/kernel/arch/x86_64/arch_elf.cpp | 82 ++++++++++++++ src/system/kernel/arch/x86_64/arch_int.cpp | 58 ++++++++++ .../kernel/arch/x86_64/arch_platform.cpp | 35 ++++++ .../arch/x86_64/arch_real_time_clock.cpp | 45 ++++++++ src/system/kernel/arch/x86_64/arch_smp.cpp | 37 ++++++ .../kernel/arch/x86_64/arch_system_info.cpp | 21 ++++ src/system/kernel/arch/x86_64/arch_thread.cpp | 104 +++++++++++++++++ src/system/kernel/arch/x86_64/arch_timer.cpp | 30 +++++ .../kernel/arch/x86_64/arch_user_debugger.cpp | 106 ++++++++++++++++++ src/system/kernel/arch/x86_64/arch_vm.cpp | 66 +++++++++++ .../arch/x86_64/arch_vm_translation_map.cpp | 52 +++++++++ 17 files changed, 904 insertions(+), 4 deletions(-) create mode 100644 src/system/kernel/arch/x86_64/arch_commpage.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_debug.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_debug_console.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_elf.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_int.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_platform.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_real_time_clock.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_smp.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_system_info.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_thread.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_timer.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_user_debugger.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_vm.cpp create mode 100644 src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp diff --git a/headers/private/kernel/arch/x86_64/arch_int.h b/headers/private/kernel/arch/x86_64/arch_int.h index 9507d6de6d..9e8e987c78 100644 --- a/headers/private/kernel/arch/x86_64/arch_int.h +++ b/headers/private/kernel/arch/x86_64/arch_int.h @@ -34,7 +34,7 @@ static inline void arch_int_restore_interrupts_inline(int oldState) { if (oldState) - asm("sti"); + asm("sti"); } diff --git a/src/system/kernel/arch/x86_64/Jamfile b/src/system/kernel/arch/x86_64/Jamfile index 5f05fb5103..9765aad4f0 100644 --- a/src/system/kernel/arch/x86_64/Jamfile +++ b/src/system/kernel/arch/x86_64/Jamfile @@ -7,7 +7,21 @@ UsePrivateKernelHeaders ; UsePrivateHeaders shared ; KernelMergeObject kernel_arch_x86_64.o : + arch_commpage.cpp arch_cpu.cpp + arch_debug.cpp + arch_debug_console.cpp + arch_elf.cpp + arch_int.cpp + arch_platform.cpp + arch_real_time_clock.cpp + arch_smp.cpp + arch_system_info.cpp + arch_thread.cpp + arch_timer.cpp + arch_user_debugger.cpp + arch_vm.cpp + arch_vm_translation_map.cpp : $(TARGET_KERNEL_PIC_CCFLAGS) ; diff --git a/src/system/kernel/arch/x86_64/arch_commpage.cpp b/src/system/kernel/arch/x86_64/arch_commpage.cpp new file mode 100644 index 0000000000..5dcb59870f --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_commpage.cpp @@ -0,0 +1,21 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +status_t +arch_commpage_init(void) +{ + return B_OK; +} + + +status_t +arch_commpage_init_post_cpus(void) +{ + return B_OK; +} diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp b/src/system/kernel/arch/x86_64/arch_cpu.cpp index 0138f06af8..108b4d1621 100644 --- a/src/system/kernel/arch/x86_64/arch_cpu.cpp +++ b/src/system/kernel/arch/x86_64/arch_cpu.cpp @@ -1,6 +1,10 @@ /* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk + * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. */ @@ -8,8 +12,6 @@ #include -// #pragma mark - - status_t arch_cpu_preboot_init_percpu(kernel_args *args, int cpu) @@ -46,6 +48,13 @@ arch_cpu_init_post_modules(kernel_args *args) } +void +arch_cpu_user_TLB_invalidate(void) +{ + +} + + void arch_cpu_global_TLB_invalidate(void) { @@ -102,6 +111,33 @@ error: } +status_t +arch_cpu_user_memcpy(void *to, const void *from, size_t size, + addr_t *faultHandler) +{ + char *d = (char *)to; + const char *s = (const char *)from; + addr_t oldFaultHandler = *faultHandler; + + // this check is to trick the gcc4 compiler and have it keep the error label + if (s == NULL) + goto error; + + *faultHandler = (addr_t)&&error; + + for (; size != 0; size--) { + *d++ = *s++; + } + + *faultHandler = oldFaultHandler; + return 0; + +error: + *faultHandler = oldFaultHandler; + return B_BAD_ADDRESS; +} + + status_t arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) { diff --git a/src/system/kernel/arch/x86_64/arch_debug.cpp b/src/system/kernel/arch/x86_64/arch_debug.cpp new file mode 100644 index 0000000000..b9946bb186 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_debug.cpp @@ -0,0 +1,102 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +void +arch_debug_save_registers(struct arch_debug_registers* registers) +{ + +} + + +void +arch_debug_stack_trace(void) +{ + +} + + +bool +arch_debug_contains_call(Thread *thread, const char *symbol, + addr_t start, addr_t end) +{ + return false; +} + + +void * +arch_debug_get_caller(void) +{ + return NULL; +} + + +int32 +arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipIframes, int32 skipFrames, uint32 flags) +{ + return 0; +} + + +void* +arch_debug_get_interrupt_pc(bool* _isSyscall) +{ + return NULL; +} + + +void +arch_debug_unset_current_thread(void) +{ + +} + + +bool +arch_is_debug_variable_defined(const char* variableName) +{ + return false; +} + + +status_t +arch_set_debug_variable(const char* variableName, uint64 value) +{ + return B_OK; +} + + +status_t +arch_get_debug_variable(const char* variableName, uint64* value) +{ + return B_OK; +} + + +ssize_t +arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) +{ + return B_ERROR; +} + + +status_t +arch_debug_init(kernel_args *args) +{ + return B_OK; +} + +void +arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, + void (*function)(void*), void* parameter) +{ + // To be implemented in asm, not here. +} diff --git a/src/system/kernel/arch/x86_64/arch_debug_console.cpp b/src/system/kernel/arch/x86_64/arch_debug_console.cpp new file mode 100644 index 0000000000..cae226df4b --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_debug_console.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + + +void +arch_debug_remove_interrupt_handler(uint32 line) +{ + +} + + +void +arch_debug_install_interrupt_handlers(void) +{ + +} + + +int +arch_debug_blue_screen_try_getchar(void) +{ + return -1; +} + + +char +arch_debug_blue_screen_getchar(void) +{ + while(true) + PAUSE(); + return 0; +} + + +int +arch_debug_serial_try_getchar(void) +{ + return -1; +} + + +char +arch_debug_serial_getchar(void) +{ + while(true) + PAUSE(); + return 0; +} + + +void +arch_debug_serial_putchar(const char c) +{ + +} + + +void +arch_debug_serial_puts(const char *s) +{ + +} + + +void +arch_debug_serial_early_boot_message(const char *string) +{ + +} + + +status_t +arch_debug_console_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_debug_console_init_settings(kernel_args *args) +{ + return B_OK; +} diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp new file mode 100644 index 0000000000..f8c6ad280e --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_elf.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +// Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. + +status_t +elf_load_user_image(const char *path, Team *team, int flags, addr_t *_entry) +{ + return B_ERROR; +} + +image_id +load_kernel_add_on(const char *path) +{ + return 0; +} + +status_t +unload_kernel_add_on(image_id id) +{ + return B_ERROR; +} + +status_t +elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, + const char **_symbolName, const char **_imageName, bool *_exactMatch) +{ + return B_ERROR; +} + +addr_t +elf_debug_lookup_symbol(const char* searchName) +{ + return 0; +} + +struct elf_image_info * +elf_get_kernel_image() +{ + return NULL; +} + +image_id +elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, + addr_t data, size_t dataSize) +{ + return B_ERROR; +} + +status_t +elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, + size_t size, int32 type) +{ + return B_ERROR; +} + +status_t +elf_init(struct kernel_args *args) +{ + return B_OK; +} + +status_t +get_image_symbol(image_id image, const char *name, int32 symbolType, + void **_symbolLocation) +{ + return B_OK; +} + +status_t +_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, + int32* _symbolCount, char* stringTable, size_t* _stringTableSize, + addr_t* _imageDelta) +{ + return B_ERROR; +} diff --git a/src/system/kernel/arch/x86_64/arch_int.cpp b/src/system/kernel/arch/x86_64/arch_int.cpp new file mode 100644 index 0000000000..b196a92476 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_int.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +void +arch_int_enable_io_interrupt(int irq) +{ + +} + + +void +arch_int_disable_io_interrupt(int irq) +{ + +} + + +void +arch_int_configure_io_interrupt(int irq, uint32 config) +{ + +} + + +status_t +arch_int_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_int_init_post_vm(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_int_init_io(kernel_args* args) +{ + return B_OK; +} + + +status_t +arch_int_init_post_device_manager(struct kernel_args *args) +{ + return B_OK; +} diff --git a/src/system/kernel/arch/x86_64/arch_platform.cpp b/src/system/kernel/arch/x86_64/arch_platform.cpp new file mode 100644 index 0000000000..c556b5639d --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_platform.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include +//#include + + +status_t +arch_platform_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_platform_init_post_vm(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_platform_init_post_thread(struct kernel_args *args) +{ + //apm_init(args); + return B_OK; +} + diff --git a/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp b/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp new file mode 100644 index 0000000000..1ada20b9ea --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + + +status_t +arch_rtc_init(struct kernel_args *args, struct real_time_data *data) +{ + return B_OK; +} + + +uint32 +arch_rtc_get_hw_time(void) +{ + return 0; +} + + +void +arch_rtc_set_hw_time(uint32 seconds) +{ + +} + + +void +arch_rtc_set_system_time_offset(struct real_time_data *data, bigtime_t offset) +{ + +} + + +bigtime_t +arch_rtc_get_system_time_offset(struct real_time_data *data) +{ + return 0; +} diff --git a/src/system/kernel/arch/x86_64/arch_smp.cpp b/src/system/kernel/arch/x86_64/arch_smp.cpp new file mode 100644 index 0000000000..c8a6657378 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_smp.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +status_t +arch_smp_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_smp_per_cpu_init(kernel_args *args, int32 cpu) +{ + return B_OK; +} + + +void +arch_smp_send_broadcast_ici(void) +{ + +} + + +void +arch_smp_send_ici(int32 target_cpu) +{ + +} diff --git a/src/system/kernel/arch/x86_64/arch_system_info.cpp b/src/system/kernel/arch/x86_64/arch_system_info.cpp new file mode 100644 index 0000000000..b9f1d7b31e --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_system_info.cpp @@ -0,0 +1,21 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +status_t +arch_get_system_info(system_info *info, size_t size) +{ + return B_OK; +} + + +status_t +arch_system_info_init(struct kernel_args *args) +{ + return B_OK; +} diff --git a/src/system/kernel/arch/x86_64/arch_thread.cpp b/src/system/kernel/arch/x86_64/arch_thread.cpp new file mode 100644 index 0000000000..d09c11ab9d --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_thread.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + + +status_t +arch_thread_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_team_init_team_struct(Team *p, bool kernel) +{ + return B_ERROR; +} + + +status_t +arch_thread_init_thread_struct(Thread *thread) +{ + return B_ERROR; +} + + +void +arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, + void (*function)(void*), const void* data) +{ + +} + + +status_t +arch_thread_init_tls(Thread *thread) +{ + return B_ERROR; +} + + +void +arch_thread_context_switch(Thread *from, Thread *to) +{ + +} + + +void +arch_thread_dump_info(void *info) +{ + +} + + +status_t +arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, + void* args2) +{ + return B_ERROR; +} + + +bool +arch_on_signal_stack(Thread *thread) +{ + return false; +} + + +status_t +arch_setup_signal_frame(Thread* thread, struct sigaction* action, + struct signal_frame_data* signalFrameData) +{ + return B_ERROR; +} + + +int64 +arch_restore_signal_frame(struct signal_frame_data* signalFrameData) +{ + return 0; +} + + +void +arch_store_fork_frame(struct arch_fork_arg *arg) +{ + +} + + +void +arch_restore_fork_frame(struct arch_fork_arg* arg) +{ + +} diff --git a/src/system/kernel/arch/x86_64/arch_timer.cpp b/src/system/kernel/arch/x86_64/arch_timer.cpp new file mode 100644 index 0000000000..c320b6bf98 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_timer.cpp @@ -0,0 +1,30 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +void +arch_timer_set_hardware_timer(bigtime_t timeout) +{ + +} + + +void +arch_timer_clear_hardware_timer(void) +{ + +} + + +int +arch_init_timer(kernel_args *args) +{ + return 0; +} diff --git a/src/system/kernel/arch/x86_64/arch_user_debugger.cpp b/src/system/kernel/arch/x86_64/arch_user_debugger.cpp new file mode 100644 index 0000000000..a9931c674d --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_user_debugger.cpp @@ -0,0 +1,106 @@ +/* + * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +// The software breakpoint instruction (int3). +const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; + + +void +arch_clear_team_debug_info(struct arch_team_debug_info *info) +{ + +} + + +void +arch_destroy_team_debug_info(struct arch_team_debug_info *info) +{ + +} + + +void +arch_clear_thread_debug_info(struct arch_thread_debug_info *info) +{ + +} + + +void +arch_destroy_thread_debug_info(struct arch_thread_debug_info *info) +{ + +} + + +void +arch_update_thread_single_step() +{ + +} + + +void +arch_set_debug_cpu_state(const debug_cpu_state *cpuState) +{ + +} + + +void +arch_get_debug_cpu_state(debug_cpu_state *cpuState) +{ + +} + + +status_t +arch_set_breakpoint(void *address) +{ + return B_OK; +} + + +status_t +arch_clear_breakpoint(void *address) +{ + return B_OK; +} + + +status_t +arch_set_watchpoint(void *address, uint32 type, int32 length) +{ + return B_OK; +} + + +status_t +arch_clear_watchpoint(void *address) +{ + return B_OK; +} + + +bool +arch_has_breakpoints(struct arch_team_debug_info *info) +{ + return false; +} + + +void +x86_init_user_debug() +{ + +} + diff --git a/src/system/kernel/arch/x86_64/arch_vm.cpp b/src/system/kernel/arch/x86_64/arch_vm.cpp new file mode 100644 index 0000000000..db842ad6d3 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_vm.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +status_t +arch_vm_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_post_area(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_end(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_post_modules(kernel_args *args) +{ + return B_OK; +} + + +void +arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to) +{ + +} + + +bool +arch_vm_supports_protection(uint32 protection) +{ + return true; +} + + +void +arch_vm_unset_memory_type(struct VMArea *area) +{ + +} + + +status_t +arch_vm_set_memory_type(struct VMArea *area, phys_addr_t physicalBase, + uint32 type) +{ + return B_OK; +} diff --git a/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp new file mode 100644 index 0000000000..be0f2d1a40 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +status_t +arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map) +{ + return B_ERROR; +} + + +status_t +arch_vm_translation_map_init(kernel_args *args, + VMPhysicalPageMapper** _physicalPageMapper) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_init_post_sem(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_init_post_area(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_early_map(kernel_args *args, addr_t va, phys_addr_t pa, + uint8 attributes, phys_addr_t (*get_free_page)(kernel_args *)) +{ + return B_ERROR; +} + + +bool +arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, + uint32 protection) +{ + return true; +} From 6296722bc0d7b1cbe76111937ad147c850f9bfdc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 16 Jun 2012 11:20:05 +0100 Subject: [PATCH 015/273] Fixed incorrect link address in kernel linker script. --- src/system/ldscripts/x86_64/kernel.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/ldscripts/x86_64/kernel.ld b/src/system/ldscripts/x86_64/kernel.ld index f3db82d1d8..070379289a 100644 --- a/src/system/ldscripts/x86_64/kernel.ld +++ b/src/system/ldscripts/x86_64/kernel.ld @@ -4,7 +4,7 @@ OUTPUT_ARCH("i386:x86-64") ENTRY(_start) SECTIONS { - . = 0xFFFFFF8000000000 + SIZEOF_HEADERS; + . = 0xFFFFFFFF80000000 + SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } From e114f50ddd4eb9fa71c4d375e6c8cd7dfbc0b0f3 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 19 Jun 2012 20:38:53 +0100 Subject: [PATCH 016/273] Fixed bootloader build under x86_64. --- headers/private/kernel/arch/x86_64/arch_system_info.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/headers/private/kernel/arch/x86_64/arch_system_info.h b/headers/private/kernel/arch/x86_64/arch_system_info.h index 9137e0765f..393f297d59 100644 --- a/headers/private/kernel/arch/x86_64/arch_system_info.h +++ b/headers/private/kernel/arch/x86_64/arch_system_info.h @@ -13,9 +13,11 @@ extern "C" { #endif -//status_t get_current_cpuid(cpuid_info *info, uint32 eax); -//uint32 get_eflags(void); -//void set_eflags(uint32 value); +#ifdef _BOOT_MODE +status_t get_current_cpuid(cpuid_info *info, uint32 eax); +uint32 get_eflags(void); +void set_eflags(uint32 value); +#endif //status_t _user_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); From 7c488bff706843c85363614f024787024eebbb9b Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 19 Jun 2012 21:36:13 +0100 Subject: [PATCH 017/273] Modified the floppy boot image target so that it can be used to build an x86_64 boot image. * set_haiku_revision doesn't currently support ELF64, don't use a revisioned kernel image on x86_64 for now. * Don't try to build add-ons for x86_64 yet. --- build/jam/FloppyBootImage | 99 +++++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index ea05ca505b..1af9d5b7eb 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -52,44 +52,51 @@ SYSTEM_ADD_ONS_BUS_MANAGERS = $(X86_ONLY)acpi $(ATA_ONLY)ata config_manager dpc SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; -# modules -AddFilesToFloppyBootArchive system add-ons kernel bus_managers - : $(SYSTEM_ADD_ONS_BUS_MANAGERS) ; -AddFilesToFloppyBootArchive system add-ons kernel busses ide - : generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata it8211 ; -AddFilesToFloppyBootArchive system add-ons kernel busses scsi - : ahci ; -AddFilesToFloppyBootArchive system add-ons kernel console : vga_text ; -AddFilesToFloppyBootArchive system add-ons kernel file_systems - : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; -AddFilesToFloppyBootArchive system add-ons kernel generic - : $(ATA_ONLY)ata_adapter $(IDE_ONLY)ide_adapter locked_pool scsi_periph ; -AddFilesToFloppyBootArchive system add-ons kernel partitioning_systems - : intel session ; -AddFilesToFloppyBootArchive system add-ons kernel interrupt_controllers - : $(PPC_ONLY)openpic ; +if $(TARGET_ARCH) != x86_64 { + # modules + AddFilesToFloppyBootArchive system add-ons kernel bus_managers + : $(SYSTEM_ADD_ONS_BUS_MANAGERS) ; + AddFilesToFloppyBootArchive system add-ons kernel busses ide + : generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata it8211 ; + AddFilesToFloppyBootArchive system add-ons kernel busses scsi + : ahci ; + AddFilesToFloppyBootArchive system add-ons kernel console : vga_text ; + AddFilesToFloppyBootArchive system add-ons kernel file_systems + : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; + AddFilesToFloppyBootArchive system add-ons kernel generic + : $(ATA_ONLY)ata_adapter $(IDE_ONLY)ide_adapter locked_pool scsi_periph ; + AddFilesToFloppyBootArchive system add-ons kernel partitioning_systems + : intel session ; + AddFilesToFloppyBootArchive system add-ons kernel interrupt_controllers + : $(PPC_ONLY)openpic ; -if $(USB_BOOT) = 1 { - AddFilesToFloppyBootArchive system add-ons kernel busses usb - : uhci ohci ehci ; -} + if $(USB_BOOT) = 1 { + AddFilesToFloppyBootArchive system add-ons kernel busses usb + : uhci ohci ehci ; + } -if $(TARGET_ARCH) = x86 { - AddFilesToFloppyBootArchive system add-ons kernel cpu : generic_x86 ; -} + if $(TARGET_ARCH) = x86 { + AddFilesToFloppyBootArchive system add-ons kernel cpu : generic_x86 ; + } -# drivers -AddNewDriversToFloppyBootArchive disk scsi : scsi_cd scsi_disk ; -if $(USB_BOOT) = 1 { - AddDriversToFloppyBootArchive disk usb : usb_disk ; -} -if $(NET_BOOT) = 1 { - AddDriversToFloppyBootArchive disk virtual : remote_disk ; - AddDriversToFloppyBootArchive net : $(SYSTEM_ADD_ONS_DRIVERS_NET) ; + # drivers + AddNewDriversToFloppyBootArchive disk scsi : scsi_cd scsi_disk ; + if $(USB_BOOT) = 1 { + AddDriversToFloppyBootArchive disk usb : usb_disk ; + } + if $(NET_BOOT) = 1 { + AddDriversToFloppyBootArchive disk virtual : remote_disk ; + AddDriversToFloppyBootArchive net : $(SYSTEM_ADD_ONS_DRIVERS_NET) ; + } } # kernel -AddFilesToFloppyBootArchive system : kernel_$(TARGET_ARCH) ; +if $(TARGET_ARCH) = x86_64 { + # TODO x86_64: ELF64 support not added to set_haiku_revision. + AddFilesToFloppyBootArchive system : kernel_$(TARGET_ARCH) ; +} else { + AddFilesToFloppyBootArchive system : kernel_$(TARGET_ARCH) ; +} # scripts and data files @@ -114,19 +121,21 @@ if $(NET_BOOT) = 1 { } # boot module links -AddBootModuleSymlinksToFloppyBootArchive - $(SYSTEM_ADD_ONS_BUS_MANAGERS) - $(PPC_ONLY)openpic - $(ATA_ONLY)ata_adapter $(IDE_ONLY)ide_adapter locked_pool scsi_periph - $(X86_ONLY)generic_x86 - ahci generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata - it8211 - $(USB_ONLY)uhci $(USB_ONLY)ohci $(USB_ONLY)ehci - scsi_cd scsi_disk $(USB_ONLY)usb_disk - intel session - $(SYSTEM_ADD_ONS_FILE_SYSTEMS) - $(BOOT_ADD_ONS_NET) -; +if $(TARGET_ARCH) != x86_64 { + AddBootModuleSymlinksToFloppyBootArchive + $(SYSTEM_ADD_ONS_BUS_MANAGERS) + $(PPC_ONLY)openpic + $(ATA_ONLY)ata_adapter $(IDE_ONLY)ide_adapter locked_pool scsi_periph + $(X86_ONLY)generic_x86 + ahci generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata + it8211 + $(USB_ONLY)uhci $(USB_ONLY)ohci $(USB_ONLY)ehci + scsi_cd scsi_disk $(USB_ONLY)usb_disk + intel session + $(SYSTEM_ADD_ONS_FILE_SYSTEMS) + $(BOOT_ADD_ONS_NET) + ; +} #pragma mark - Build The Archive From cfd1c1802f3c3250f96a14db3c65eed4667f09db Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 19 Jun 2012 21:54:40 +0100 Subject: [PATCH 018/273] Add -march=pentium to boot {CC,C++}FLAGS on x86_64, prevents GCC from generating SSE code. --- build/jam/BuildSetup | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index f0f30fbf3c..690227cb67 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -391,8 +391,8 @@ switch $(HAIKU_ARCH) { # Bootloader is 32-bit. HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; - HAIKU_BOOT_CCFLAGS += -m32 ; - HAIKU_BOOT_C++FLAGS += -m32 ; + HAIKU_BOOT_CCFLAGS += -m32 -march=pentium ; + HAIKU_BOOT_C++FLAGS += -m32 -march=pentium ; # Enable use of the gcc built-in atomic functions instead of atomic_*(). # The former are inlined and have thus less overhead. From 7417d5ed8deef641a6941e5a17a47781b8f8959c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 20 Jun 2012 10:44:38 +0100 Subject: [PATCH 019/273] Made the bootloader search for both kernel_x86 and kernel_x86_64 when built for x86 or x86_64. --- src/system/boot/loader/Jamfile | 12 +++++++ src/system/boot/loader/loader.cpp | 56 ++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index 1cb962c7d7..00135e2711 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -38,6 +38,18 @@ UsePrivateHeaders shared storage ; case "x86" : { defines += + ALTERNATE_BOOT_ARCH=\\\"x86_64\\\" + + BOOT_SUPPORT_PARTITION_EFI + + #BOOT_SUPPORT_FILE_SYSTEM_FAT + ; + } + case "x86_64" : + { + defines += + ALTERNATE_BOOT_ARCH=\\\"x86\\\" + BOOT_SUPPORT_PARTITION_EFI #BOOT_SUPPORT_FILE_SYSTEM_FAT diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index fb5c2b41dd..7fd888b3c2 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -24,11 +24,24 @@ # error BOOT_ARCH has to be defined to differentiate the kernel per platform #endif -#define KERNEL_IMAGE "kernel_" BOOT_ARCH -#define KERNEL_PATH "system/" KERNEL_IMAGE +#define KERNEL_IMAGE "kernel_" BOOT_ARCH +#define KERNEL_PATH "system/" KERNEL_IMAGE + +#ifdef ALTERNATE_BOOT_ARCH +# define ALTERNATE_KERNEL_IMAGE "kernel_" ALTERNATE_BOOT_ARCH +# define ALTERNATE_KERNEL_PATH "system/" ALTERNATE_KERNEL_IMAGE +#endif -static const char *sPaths[] = { +static const char *sKernelPaths[][2] = { + { KERNEL_PATH, KERNEL_IMAGE }, +#ifdef ALTERNATE_BOOT_ARCH + { ALTERNATE_KERNEL_PATH, ALTERNATE_KERNEL_IMAGE }, +#endif + { NULL, NULL }, +}; + +static const char *sAddonPaths[] = { kVolumeLocalSystemKernelAddonsDirectory, kVolumeLocalCommonKernelAddonsDirectory, kVolumeLocalUserKernelAddonsDirectory, @@ -36,6 +49,22 @@ static const char *sPaths[] = { }; +static int +find_kernel(Directory *volume, const char **name = NULL) +{ + for (int32 i = 0; sKernelPaths[i][0] != NULL; i++) { + int fd = open_from(volume, sKernelPaths[i][0], O_RDONLY); + if (fd >= 0) { + if (name) + *name = sKernelPaths[i][1]; + + return fd; + } + } + + return B_ENTRY_NOT_FOUND; +} + bool is_bootable(Directory *volume) { @@ -43,7 +72,7 @@ is_bootable(Directory *volume) return false; // check for the existance of a kernel (for our platform) - int fd = open_from(volume, KERNEL_PATH, O_RDONLY); + int fd = find_kernel(volume); if (fd < B_OK) return false; @@ -56,11 +85,12 @@ is_bootable(Directory *volume) status_t load_kernel(stage2_args *args, Directory *volume) { - int fd = open_from(volume, KERNEL_PATH, O_RDONLY); + const char *name; + int fd = find_kernel(volume, &name); if (fd < B_OK) return fd; - dprintf("load kernel...\n"); + dprintf("load kernel %s...\n", name); elf_init(); status_t status = elf_load_image(fd, &gKernelArgs.kernel_image); @@ -78,7 +108,7 @@ load_kernel(stage2_args *args, Directory *volume) return status; } - gKernelArgs.kernel_image.name = kernel_args_strdup(KERNEL_IMAGE); + gKernelArgs.kernel_image.name = kernel_args_strdup(name); return B_OK; } @@ -129,9 +159,9 @@ load_module(Directory *volume, const char *name) if (strlcpy(moduleName, name, sizeof(moduleName)) > sizeof(moduleName)) return B_NAME_TOO_LONG; - for (int32 i = 0; sPaths[i]; i++) { + for (int32 i = 0; sAddonPaths[i]; i++) { // get base path - int baseFD = open_from(volume, sPaths[i], O_RDONLY); + int baseFD = open_from(volume, sAddonPaths[i], O_RDONLY); if (baseFD < B_OK) continue; @@ -179,9 +209,9 @@ load_modules(stage2_args *args, Directory *volume) // ToDo: this should be mostly replaced by a hardware oriented detection mechanism int32 i = 0; - for (; sPaths[i]; i++) { + for (; sAddonPaths[i]; i++) { char path[B_FILE_NAME_LENGTH]; - snprintf(path, sizeof(path), "%s/boot", sPaths[i]); + snprintf(path, sizeof(path), "%s/boot", sAddonPaths[i]); if (load_modules_from(volume, path) != B_OK) failed++; @@ -195,7 +225,7 @@ load_modules(stage2_args *args, Directory *volume) for (int32 i = 0; paths[i]; i++) { char path[B_FILE_NAME_LENGTH]; - snprintf(path, sizeof(path), "%s/%s", sPaths[0], paths[i]); + snprintf(path, sizeof(path), "%s/%s", sAddonPaths[0], paths[i]); load_modules_from(volume, path); } } @@ -220,7 +250,7 @@ load_modules(stage2_args *args, Directory *volume) // as this piece will survive a more intelligent module // loading approach... char path[B_FILE_NAME_LENGTH]; - snprintf(path, sizeof(path), "%s/%s", sPaths[0], "file_systems"); + snprintf(path, sizeof(path), "%s/%s", sAddonPaths[0], "file_systems"); load_modules_from(volume, path); } From 93cb9538be54a2dd4ab6097453ac7d521a9a0b6c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 20 Jun 2012 11:53:47 +0100 Subject: [PATCH 020/273] Don't store a KMessage in kernel_args for the boot volume, only the buffer address/size. Pointers in kernel_args are going to be changed to unconditionally use 64-bit storage (to make kernel_args compatible with both the x86 and x86_64 kernels). KMessage stores a pointer to its buffer, however since KMessage is used outside of the boot code it is undesirable to change it to use 64-bit storage for the pointer as it may add additional overhead on 32-bit builds. Therefore, only store the buffer address and size and then construct a KMessage from those in the kernel. --- headers/private/kernel/boot/kernel_args.h | 6 ++--- headers/private/kernel/boot/stage2.h | 2 ++ src/system/boot/loader/kernel_args.cpp | 1 + src/system/boot/loader/loader.cpp | 3 +-- src/system/boot/loader/main.cpp | 11 ++++----- src/system/boot/loader/menu.cpp | 4 ++-- src/system/boot/loader/partitions.cpp | 8 +++---- src/system/boot/loader/vfs.cpp | 3 +-- .../boot/platform/amiga_m68k/devices.cpp | 3 +-- .../boot/platform/atari_m68k/devices.cpp | 7 +++--- .../boot/platform/bios_ia32/devices.cpp | 11 ++++----- src/system/boot/platform/cfe/devices.cpp | 4 ++-- .../boot/platform/openfirmware/devices.cpp | 4 ++-- src/system/boot/platform/pxe_ia32/devices.cpp | 13 +++++------ src/system/kernel/fs/vfs_boot.cpp | 23 ++++++++++--------- 15 files changed, 49 insertions(+), 54 deletions(-) diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index 5d226e5aa1..a6356590e9 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -18,8 +18,6 @@ #include #include -#include - #define CURRENT_KERNEL_ARGS_VERSION 1 #define MAX_KERNEL_ARGS_RANGE 20 @@ -59,7 +57,9 @@ typedef struct kernel_args { uint32 num_cpus; addr_range cpu_kstack[MAX_BOOT_CPUS]; - KMessage boot_volume; + // boot volume KMessage data + void *boot_volume; + int32 boot_volume_size; struct driver_settings_file *driver_settings; diff --git a/headers/private/kernel/boot/stage2.h b/headers/private/kernel/boot/stage2.h index ce31fcbf89..7e18a9263a 100644 --- a/headers/private/kernel/boot/stage2.h +++ b/headers/private/kernel/boot/stage2.h @@ -8,10 +8,12 @@ #include +#include struct stage2_args; extern struct kernel_args gKernelArgs; +extern KMessage gBootVolume; #ifdef __cplusplus extern "C" { diff --git a/src/system/boot/loader/kernel_args.cpp b/src/system/boot/loader/kernel_args.cpp index bf7ebd4d92..9956e80017 100644 --- a/src/system/boot/loader/kernel_args.cpp +++ b/src/system/boot/loader/kernel_args.cpp @@ -19,6 +19,7 @@ static const size_t kChunkSize = 16 * B_PAGE_SIZE; kernel_args gKernelArgs; +KMessage gBootVolume; static void* sFirstFree; static void* sLast; diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index 7fd888b3c2..074bef5b3b 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -233,8 +233,7 @@ load_modules(stage2_args *args, Directory *volume) // and now load all partitioning and file system modules // needed to identify the boot volume - if (!gKernelArgs.boot_volume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, - false)) { + if (!gBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) { // iterate over the mounted volumes and load their file system Partition *partition; if (gRoot->GetPartitionFor(volume, &partition) == B_OK) { diff --git a/src/system/boot/loader/main.cpp b/src/system/boot/loader/main.cpp index bc67e3a9ab..63a78a1e9a 100644 --- a/src/system/boot/loader/main.cpp +++ b/src/system/boot/loader/main.cpp @@ -40,9 +40,6 @@ main(stage2_args *args) gKernelArgs.keep_debug_output_buffer = true; #endif - // construct boot_volume KMessage explicitely - new(&gKernelArgs.boot_volume) KMessage; - add_stage2_driver_settings(args); platform_init_video(); @@ -123,16 +120,16 @@ main(stage2_args *args) // clone the boot_volume KMessage into kernel accessible memory // note, that we need to 4 byte align the buffer and thus allocate // 3 more bytes - KMessage& bootVolume = gKernelArgs.boot_volume; - void* buffer = kernel_args_malloc(bootVolume.ContentSize() + 3); + void* buffer = kernel_args_malloc(gBootVolume.ContentSize() + 3); if (!buffer) { panic("Could not allocate memory for the boot volume kernel " "arguments"); } buffer = (void*)(((addr_t)buffer + 3) & ~(addr_t)0x3); - memcpy(buffer, bootVolume.Buffer(), bootVolume.ContentSize()); - bootVolume.SetTo(buffer, bootVolume.ContentSize()); + memcpy(buffer, gBootVolume.Buffer(), gBootVolume.ContentSize()); + gKernelArgs.boot_volume = buffer; + gKernelArgs.boot_volume_size = gBootVolume.ContentSize(); // ToDo: cleanup, heap_release() etc. platform_start_kernel(); diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index ef15a2a9ff..e0f6b2b138 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -481,7 +481,7 @@ user_menu_boot_volume(Menu* menu, MenuItem* item) bootItem->Select(true); bootItem->SetData(item->Data()); - gKernelArgs.boot_volume.SetBool(BOOT_VOLUME_USER_SELECTED, true); + gBootVolume.SetBool(BOOT_VOLUME_USER_SELECTED, true); return true; } @@ -712,7 +712,7 @@ add_boot_volume_menu(Directory* bootVolume) menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); item->SetType(MENU_ITEM_NO_CHOICE); - if (gKernelArgs.boot_volume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) + if (gBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) menu->SetChoiceText("CD-ROM or hard drive"); return menu; diff --git a/src/system/boot/loader/partitions.cpp b/src/system/boot/loader/partitions.cpp index fd74561b1f..29d4f20f76 100644 --- a/src/system/boot/loader/partitions.cpp +++ b/src/system/boot/loader/partitions.cpp @@ -268,8 +268,8 @@ Partition::_Mount(file_system_module_info *module, Directory **_fileSystem) status_t Partition::Mount(Directory **_fileSystem, bool isBootDevice) { - if (isBootDevice && gKernelArgs.boot_volume.GetBool( - BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) { + if (isBootDevice && gBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, + false)) { return _Mount(&gTarFileSystemModule, _fileSystem); } @@ -293,8 +293,8 @@ Partition::Scan(bool mountFileSystems, bool isBootDevice) // if we were not booted from the real boot device, we won't scan // the device we were booted from (which is likely to be a slow // floppy or CD) - if (isBootDevice && gKernelArgs.boot_volume.GetBool( - BOOT_VOLUME_BOOTED_FROM_IMAGE, false)) { + if (isBootDevice && gBootVolume.GetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, + false)) { return B_ENTRY_NOT_FOUND; } diff --git a/src/system/boot/loader/vfs.cpp b/src/system/boot/loader/vfs.cpp index 2d532309c0..9c1d5e1e1f 100644 --- a/src/system/boot/loader/vfs.cpp +++ b/src/system/boot/loader/vfs.cpp @@ -380,8 +380,7 @@ register_boot_file_system(Directory *volume) return status; } - gKernelArgs.boot_volume.SetInt64(BOOT_VOLUME_PARTITION_OFFSET, - partition->offset); + gBootVolume.SetInt64(BOOT_VOLUME_PARTITION_OFFSET, partition->offset); Node *device = get_node_from(partition->FD()); if (device == NULL) { diff --git a/src/system/boot/platform/amiga_m68k/devices.cpp b/src/system/boot/platform/amiga_m68k/devices.cpp index 5d4e73409e..4030f0242b 100644 --- a/src/system/boot/platform/amiga_m68k/devices.cpp +++ b/src/system/boot/platform/amiga_m68k/devices.cpp @@ -161,8 +161,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) TRACE(("boot drive ID: %x\n", gBootDriveID)); //TODO - gKernelArgs.boot_volume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, - gBootedFromImage); + gBootVolume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, gBootedFromImage); return B_OK; } diff --git a/src/system/boot/platform/atari_m68k/devices.cpp b/src/system/boot/platform/atari_m68k/devices.cpp index 8abfa678a4..93f9c5bf56 100644 --- a/src/system/boot/platform/atari_m68k/devices.cpp +++ b/src/system/boot/platform/atari_m68k/devices.cpp @@ -1182,8 +1182,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) } TRACE(("boot drive size: %Ld bytes\n", drive->Size())); - gKernelArgs.boot_volume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, - gBootedFromImage); + gBootVolume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, gBootedFromImage); return B_OK; } @@ -1232,8 +1231,8 @@ platform_register_boot_device(Node *device) check_cd_boot(drive); #endif - gKernelArgs.boot_volume.SetInt64("boot drive number", drive->DriveID()); - gKernelArgs.boot_volume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, + gBootVolume.SetInt64("boot drive number", drive->DriveID()); + gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &drive->Identifier(), sizeof(disk_identifier)); return B_OK; diff --git a/src/system/boot/platform/bios_ia32/devices.cpp b/src/system/boot/platform/bios_ia32/devices.cpp index a8cfd1b8c9..5c50c47f11 100644 --- a/src/system/boot/platform/bios_ia32/devices.cpp +++ b/src/system/boot/platform/bios_ia32/devices.cpp @@ -167,7 +167,7 @@ static bool sBlockDevicesAdded = false; static void check_cd_boot(BIOSDrive *drive) { - gKernelArgs.boot_volume.SetInt32(BOOT_METHOD, BOOT_METHOD_HARD_DISK); + gBootVolume.SetInt32(BOOT_METHOD, BOOT_METHOD_HARD_DISK); if (drive->DriveID() != 0) return; @@ -185,7 +185,7 @@ check_cd_boot(BIOSDrive *drive) specification_packet *packet = (specification_packet *)kDataSegmentScratch; if (packet->media_type != 0) - gKernelArgs.boot_volume.SetInt32(BOOT_METHOD, BOOT_METHOD_CD); + gBootVolume.SetInt32(BOOT_METHOD, BOOT_METHOD_CD); #if 0 dprintf("got CD boot spec:\n"); @@ -841,8 +841,7 @@ platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) } TRACE(("boot drive size: %Ld bytes\n", drive->Size())); - gKernelArgs.boot_volume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, - gBootedFromImage); + gBootVolume.SetBool(BOOT_VOLUME_BOOTED_FROM_IMAGE, gBootedFromImage); return B_OK; } @@ -888,8 +887,8 @@ platform_register_boot_device(Node *device) check_cd_boot(drive); - gKernelArgs.boot_volume.SetInt64("boot drive number", drive->DriveID()); - gKernelArgs.boot_volume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, + gBootVolume.SetInt64("boot drive number", drive->DriveID()); + gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &drive->Identifier(), sizeof(disk_identifier)); return B_OK; diff --git a/src/system/boot/platform/cfe/devices.cpp b/src/system/boot/platform/cfe/devices.cpp index 46a20ce82e..13e7e6c0f1 100644 --- a/src/system/boot/platform/cfe/devices.cpp +++ b/src/system/boot/platform/cfe/devices.cpp @@ -130,8 +130,8 @@ platform_register_boot_device(Node *device) disk.device_type = UNKNOWN_DEVICE; disk.device.unknown.size = device->Size(); - gKernelArgs.boot_volume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, - &disk, sizeof(disk_identifier)); + gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &disk, + sizeof(disk_identifier)); return B_OK; } diff --git a/src/system/boot/platform/openfirmware/devices.cpp b/src/system/boot/platform/openfirmware/devices.cpp index 03b00bfe4f..b58e30fe05 100644 --- a/src/system/boot/platform/openfirmware/devices.cpp +++ b/src/system/boot/platform/openfirmware/devices.cpp @@ -233,8 +233,8 @@ platform_register_boot_device(Node *device) disk.device_type = UNKNOWN_DEVICE; disk.device.unknown.size = device->Size(); - gKernelArgs.boot_volume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, - &disk, sizeof(disk_identifier)); + gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &disk, + sizeof(disk_identifier)); return B_OK; } diff --git a/src/system/boot/platform/pxe_ia32/devices.cpp b/src/system/boot/platform/pxe_ia32/devices.cpp index 7b2f9ac4e3..6dd064fc78 100644 --- a/src/system/boot/platform/pxe_ia32/devices.cpp +++ b/src/system/boot/platform/pxe_ia32/devices.cpp @@ -152,15 +152,14 @@ platform_register_boot_device(Node *device) rootPath = fileNameEnd + 1; } - KMessage& bootVolume = gKernelArgs.boot_volume; - if (bootVolume.SetInt32(BOOT_METHOD, BOOT_METHOD_NET) != B_OK - || bootVolume.AddInt64("client MAC", + if (gBootVolume.SetInt32(BOOT_METHOD, BOOT_METHOD_NET) != B_OK + || gBootVolume.AddInt64("client MAC", sTFTP.MACAddress().ToUInt64()) != B_OK - || bootVolume.AddInt32("client IP", sTFTP.IPAddress()) != B_OK - || bootVolume.AddInt32("server IP", sTFTP.ServerIPAddress()) != B_OK - || bootVolume.AddInt32("server port", sTFTP.ServerPort()) != B_OK + || gBootVolume.AddInt32("client IP", sTFTP.IPAddress()) != B_OK + || gBootVolume.AddInt32("server IP", sTFTP.ServerIPAddress()) != B_OK + || gBootVolume.AddInt32("server port", sTFTP.ServerPort()) != B_OK || (sTFTP.RootPath() - && bootVolume.AddString("net root path", rootPath) + && gBootVolume.AddString("net root path", rootPath) != B_OK)) { return B_NO_MEMORY; } diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index 0c0aba4154..b8240d71f2 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -54,6 +54,8 @@ static struct { {NULL} }; +static int32 sBootMethodType; + // This can be used by other code to see if there is a boot file system already dev_t gBootDevice = -1; bool gReadOnlyBootDevice = false; @@ -322,27 +324,28 @@ DiskBootMethod::SortPartitions(KPartition** partitions, int32 count) static status_t get_boot_partitions(kernel_args* args, PartitionStack& partitions) { - const KMessage& bootVolume = args->boot_volume; + KMessage bootVolume; + bootVolume.SetTo(args->boot_volume, args->boot_volume_size); dprintf("get_boot_partitions(): boot volume message:\n"); bootVolume.Dump(&dprintf); // create boot method - int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); + sBootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); dprintf("get_boot_partitions(): boot method type: %" B_PRId32 "\n", - bootMethodType); + sBootMethodType); BootMethod* bootMethod = NULL; - switch (bootMethodType) { + switch (sBootMethodType) { case BOOT_METHOD_NET: - bootMethod = new(nothrow) NetBootMethod(bootVolume, bootMethodType); + bootMethod = new(nothrow) NetBootMethod(bootVolume, sBootMethodType); break; case BOOT_METHOD_HARD_DISK: case BOOT_METHOD_CD: default: bootMethod = new(nothrow) DiskBootMethod(bootVolume, - bootMethodType); + sBootMethodType); break; } @@ -415,7 +418,7 @@ get_boot_partitions(kernel_args* args, PartitionStack& partitions) // sort partition list (e.g.. when booting from CD, CDs should come first in // the list) - if (!args->boot_volume.GetBool(BOOT_VOLUME_USER_SELECTED, false)) + if (!bootVolume.GetBool(BOOT_VOLUME_USER_SELECTED, false)) bootMethod->SortPartitions(partitions.Array(), partitions.CountItems()); return B_OK; @@ -513,10 +516,8 @@ vfs_mount_boot_file_system(kernel_args* args) // whether the module images the boot loader has pre-loaded are the same as // on the boot volume. That is the case when booting from hard disk or CD, // but not via network. - int32 bootMethodType = args->boot_volume.GetInt32(BOOT_METHOD, - BOOT_METHOD_DEFAULT); - bool bootingFromBootLoaderVolume = bootMethodType == BOOT_METHOD_HARD_DISK - || bootMethodType == BOOT_METHOD_CD; + bool bootingFromBootLoaderVolume = sBootMethodType == BOOT_METHOD_HARD_DISK + || sBootMethodType == BOOT_METHOD_CD; module_init_post_boot_device(bootingFromBootLoaderVolume); file_cache_init_post_boot_device(); From 192af9e0afd2f3d0cbaf5c935480343a70c8ff53 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 20 Jun 2012 14:11:24 +0100 Subject: [PATCH 021/273] Changed addr_range to use uint64. I've tested this change on x86, causing no issues. I've checked over the code for all other platforms and made the necessary changes and to the best of my knowledge they should also still work, but I haven't actually built and tested them. Once I've completed the kernel_args changes the other platforms will need testing. --- headers/private/kernel/boot/addr_range.h | 18 +++++++-------- headers/private/kernel/boot/kernel_args.h | 2 +- src/system/boot/arch/m68k/mmu.cpp | 2 +- src/system/boot/loader/kernel_args.cpp | 22 +++++++++---------- src/system/boot/loader/main.cpp | 2 +- src/system/boot/platform/amiga_m68k/mmu.cpp | 2 +- src/system/boot/platform/atari_m68k/mmu.cpp | 2 +- src/system/boot/platform/bios_ia32/mmu.cpp | 6 ++--- src/system/boot/platform/cfe/arch/ppc/mmu.cpp | 4 ++-- .../platform/openfirmware/arch/ppc/mmu.cpp | 4 ++-- .../boot/platform/raspberrypi_arm/mmu.cpp | 2 +- src/system/boot/platform/u-boot/mmu.cpp | 2 +- .../arch/arm/arch_vm_translation_map.cpp | 2 +- .../arch/m68k/arch_vm_translation_map.cpp | 2 +- .../arch/x86/arch_vm_translation_map.cpp | 2 +- src/system/kernel/fs/vfs_boot.cpp | 2 +- src/system/kernel/vm/vm.cpp | 12 +++++----- 17 files changed, 44 insertions(+), 44 deletions(-) diff --git a/headers/private/kernel/boot/addr_range.h b/headers/private/kernel/boot/addr_range.h index 1aa80e7d5a..67129eb452 100644 --- a/headers/private/kernel/boot/addr_range.h +++ b/headers/private/kernel/boot/addr_range.h @@ -11,8 +11,8 @@ typedef struct addr_range { - addr_t start; - size_t size; + uint64 start; + uint64 size; } addr_range; @@ -27,13 +27,13 @@ extern "C" { #endif status_t insert_address_range(addr_range* ranges, uint32* _numRanges, - uint32 maxRanges, addr_t start, size_t size); + uint32 maxRanges, uint64 start, uint64 size); status_t remove_address_range(addr_range* ranges, uint32* _numRanges, - uint32 maxRanges, addr_t start, size_t size); -bool get_free_address_range(addr_range* ranges, uint32 numRanges, addr_t base, - size_t size, addr_t* _rangeBase); -bool is_address_range_covered(addr_range* ranges, uint32 numRanges, addr_t base, - size_t size); + uint32 maxRanges, uint64 start, uint64 size); +bool get_free_address_range(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size, uint64* _rangeBase); +bool is_address_range_covered(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size); void sort_address_ranges(addr_range* ranges, uint32 numRanges); status_t insert_physical_address_range(phys_addr_range* ranges, @@ -48,7 +48,7 @@ void sort_physical_address_ranges(phys_addr_range* ranges, uint32 numRanges); status_t insert_physical_memory_range(phys_addr_t start, phys_size_t size); status_t insert_physical_allocated_range(phys_addr_t start, phys_size_t size); -status_t insert_virtual_allocated_range(addr_t start, size_t size); +status_t insert_virtual_allocated_range(uint64 start, uint64 size); void ignore_physical_memory_ranges_beyond_4gb(); #ifdef __cplusplus diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index a6356590e9..1922ae673d 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -58,7 +58,7 @@ typedef struct kernel_args { addr_range cpu_kstack[MAX_BOOT_CPUS]; // boot volume KMessage data - void *boot_volume; + uint64 boot_volume; int32 boot_volume_size; struct driver_settings_file *driver_settings; diff --git a/src/system/boot/arch/m68k/mmu.cpp b/src/system/boot/arch/m68k/mmu.cpp index 9c459b1e88..776fd99e1f 100644 --- a/src/system/boot/arch/m68k/mmu.cpp +++ b/src/system/boot/arch/m68k/mmu.cpp @@ -526,7 +526,7 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/loader/kernel_args.cpp b/src/system/boot/loader/kernel_args.cpp index 9956e80017..0de1205a7e 100644 --- a/src/system/boot/loader/kernel_args.cpp +++ b/src/system/boot/loader/kernel_args.cpp @@ -280,36 +280,36 @@ add_kernel_args_range(void* start, size_t size) */ extern "C" status_t insert_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, - addr_t start, size_t size) + uint64 start, uint64 size) { - return insert_range(ranges, _numRanges, + return insert_range(ranges, _numRanges, maxRanges, start, size); } extern "C" status_t remove_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, - addr_t start, size_t size) + uint64 start, uint64 size) { - return remove_range(ranges, _numRanges, + return remove_range(ranges, _numRanges, maxRanges, start, size); } bool -get_free_address_range(addr_range* ranges, uint32 numRanges, addr_t base, - size_t size, addr_t* _rangeBase) +get_free_address_range(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size, uint64* _rangeBase) { - return get_free_range(ranges, numRanges, base, + return get_free_range(ranges, numRanges, base, size, _rangeBase); } bool -is_address_range_covered(addr_range* ranges, uint32 numRanges, addr_t base, - size_t size) +is_address_range_covered(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size) { - return is_range_covered(ranges, numRanges, base, + return is_range_covered(ranges, numRanges, base, size); } @@ -389,7 +389,7 @@ insert_physical_allocated_range(phys_addr_t start, phys_size_t size) status_t -insert_virtual_allocated_range(addr_t start, size_t size) +insert_virtual_allocated_range(uint64 start, uint64 size) { return insert_address_range(gKernelArgs.virtual_allocated_range, &gKernelArgs.num_virtual_allocated_ranges, MAX_VIRTUAL_ALLOCATED_RANGE, diff --git a/src/system/boot/loader/main.cpp b/src/system/boot/loader/main.cpp index 63a78a1e9a..2af8c86316 100644 --- a/src/system/boot/loader/main.cpp +++ b/src/system/boot/loader/main.cpp @@ -128,7 +128,7 @@ main(stage2_args *args) buffer = (void*)(((addr_t)buffer + 3) & ~(addr_t)0x3); memcpy(buffer, gBootVolume.Buffer(), gBootVolume.ContentSize()); - gKernelArgs.boot_volume = buffer; + gKernelArgs.boot_volume = (addr_t)buffer; gKernelArgs.boot_volume_size = gBootVolume.ContentSize(); // ToDo: cleanup, heap_release() etc. diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp b/src/system/boot/platform/amiga_m68k/mmu.cpp index b71af83067..230b967f38 100644 --- a/src/system/boot/platform/amiga_m68k/mmu.cpp +++ b/src/system/boot/platform/amiga_m68k/mmu.cpp @@ -526,7 +526,7 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp b/src/system/boot/platform/atari_m68k/mmu.cpp index 434c4623aa..404886bd2a 100644 --- a/src/system/boot/platform/atari_m68k/mmu.cpp +++ b/src/system/boot/platform/atari_m68k/mmu.cpp @@ -526,7 +526,7 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index a808be9eaf..4c6a0c8423 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -593,9 +593,9 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base %#018" B_PRIxADDR ", length %#018" B_PRIxSIZE - "\n", gKernelArgs.virtual_allocated_range[i].start, - gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.virtual_allocated_range[i].start, + gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp index b06114fc68..2f9b2a021d 100644 --- a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp @@ -88,7 +88,7 @@ find_physical_memory_ranges(size_t &total) static bool is_virtual_allocated(void *address, size_t size) { - addr_t foundBase; + uint64 foundBase; return !get_free_address_range(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges, (addr_t)address, size, &foundBase) || foundBase != (addr_t)address; @@ -281,7 +281,7 @@ find_free_virtual_range(void *base, size_t size) void *firstFound = NULL; void *firstBaseFound = NULL; for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - void *address = (void *)(gKernelArgs.virtual_allocated_range[i].start + void *address = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start + gKernelArgs.virtual_allocated_range[i].size); if (!is_virtual_allocated(address, size)) { if (!base) diff --git a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp index 0d3e0d2810..bbe11265ce 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp @@ -170,7 +170,7 @@ find_physical_memory_ranges(size_t &total) static bool is_virtual_allocated(void *address, size_t size) { - addr_t foundBase; + uint64 foundBase; return !get_free_address_range(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges, (addr_t)address, size, &foundBase) || foundBase != (addr_t)address; @@ -462,7 +462,7 @@ find_free_virtual_range(void *base, size_t size) void *firstFound = NULL; void *firstBaseFound = NULL; for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - void *address = (void *)(gKernelArgs.virtual_allocated_range[i].start + void *address = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start + gKernelArgs.virtual_allocated_range[i].size); if (!is_virtual_allocated(address, size)) { if (!base) diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.cpp b/src/system/boot/platform/raspberrypi_arm/mmu.cpp index bf1d3d6c2f..18c39f5a39 100644 --- a/src/system/boot/platform/raspberrypi_arm/mmu.cpp +++ b/src/system/boot/platform/raspberrypi_arm/mmu.cpp @@ -591,7 +591,7 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } diff --git a/src/system/boot/platform/u-boot/mmu.cpp b/src/system/boot/platform/u-boot/mmu.cpp index bab74229fd..e38d931171 100644 --- a/src/system/boot/platform/u-boot/mmu.cpp +++ b/src/system/boot/platform/u-boot/mmu.cpp @@ -585,7 +585,7 @@ mmu_init_for_kernel(void) dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } diff --git a/src/system/kernel/arch/arm/arch_vm_translation_map.cpp b/src/system/kernel/arch/arm/arch_vm_translation_map.cpp index faad4bf263..02a042b355 100644 --- a/src/system/kernel/arch/arm/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/arm/arch_vm_translation_map.cpp @@ -71,7 +71,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); + TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); } #endif diff --git a/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp b/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp index 176f0f11a3..fc211d688a 100644 --- a/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp @@ -97,7 +97,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); + TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); } #endif switch (arch_mmu_type) { diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index aa20762e29..7b16d09c43 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -70,7 +70,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); + TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); } #endif diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index b8240d71f2..ac039fb0be 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -325,7 +325,7 @@ static status_t get_boot_partitions(kernel_args* args, PartitionStack& partitions) { KMessage bootVolume; - bootVolume.SetTo(args->boot_volume, args->boot_volume_size); + bootVolume.SetTo((void *)(addr_t)args->boot_volume, args->boot_volume_size); dprintf("get_boot_partitions(): boot volume message:\n"); bootVolume.Dump(&dprintf); diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 27ee5991b8..783872f5e5 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3585,7 +3585,7 @@ vm_free_kernel_args(kernel_args* args) TRACE(("vm_free_kernel_args()\n")); for (i = 0; i < args->num_kernel_args_ranges; i++) { - area_id area = area_for((void*)args->kernel_args_range[i].start); + area_id area = area_for((void*)(addr_t)args->kernel_args_range[i].start); if (area >= B_OK) delete_area(area); } @@ -3598,7 +3598,7 @@ allocate_kernel_args(kernel_args* args) TRACE(("allocate_kernel_args()\n")); for (uint32 i = 0; i < args->num_kernel_args_ranges; i++) { - void* address = (void*)args->kernel_args_range[i].start; + void* address = (void*)(addr_t)args->kernel_args_range[i].start; create_area("_kernel args_", &address, B_EXACT_ADDRESS, args->kernel_args_range[i].size, B_ALREADY_WIRED, @@ -3614,7 +3614,7 @@ unreserve_boot_loader_ranges(kernel_args* args) for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { vm_unreserve_address_range(VMAddressSpace::KernelID(), - (void*)args->virtual_allocated_range[i].start, + (void*)(addr_t)args->virtual_allocated_range[i].start, args->virtual_allocated_range[i].size); } } @@ -3626,13 +3626,13 @@ reserve_boot_loader_ranges(kernel_args* args) TRACE(("reserve_boot_loader_ranges()\n")); for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { - void* address = (void*)args->virtual_allocated_range[i].start; + void* address = (void*)(addr_t)args->virtual_allocated_range[i].start; // If the address is no kernel address, we just skip it. The // architecture specific code has to deal with it. if (!IS_KERNEL_ADDRESS(address)) { - dprintf("reserve_boot_loader_ranges(): Skipping range: %p, %lu\n", - address, args->virtual_allocated_range[i].size); + dprintf("reserve_boot_loader_ranges(): Skipping range: %p, %" + B_PRIu64 "\n", address, args->virtual_allocated_range[i].size); continue; } From d8efc6caf6babe278c48e8aa3277376fb68ff455 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 21 Jun 2012 18:02:23 +0100 Subject: [PATCH 022/273] Changes to kernel_args to make it identical for x86 and x86_64. * Added a FixedWidthPointer template class which uses 64-bit storage to hold a pointer. This is used in place of raw pointers in kernel_args. * Added __attribute__((packed)) to kernel_args and all structures contained within it. This is necessary due to different alignment behaviour for 32-bit and 64-bit compilation with GCC. * With these changes, kernel_args will now come out the same size for both the x86_64 kernel and the loader, excluding the preloaded_image structure which has not yet been changed. * Tested both an x86 GCC2 and GCC4 build, no problems caused by these changes. --- .../kernel/arch/x86/arch_kernel_args.h | 11 +- headers/private/kernel/boot/addr_range.h | 4 +- headers/private/kernel/boot/driver_settings.h | 3 +- headers/private/kernel/boot/elf.h | 5 +- headers/private/kernel/boot/kernel_args.h | 19 +-- .../platform/bios_ia32/platform_kernel_args.h | 6 +- .../private/kernel/util/FixedWidthPointer.h | 123 ++++++++++++++++++ src/system/boot/loader/main.cpp | 2 +- src/system/boot/platform/bios_ia32/debug.cpp | 2 +- src/system/boot/platform/bios_ia32/hpet.cpp | 2 +- src/system/boot/platform/bios_ia32/smp.cpp | 10 +- src/system/boot/platform/bios_ia32/video.cpp | 2 +- .../boot/platform/generic/video_splash.cpp | 8 +- .../boot/platform/openfirmware/video.cpp | 2 +- src/system/boot/platform/u-boot/serial.cpp | 2 +- src/system/kernel/arch/x86/apic.cpp | 2 +- src/system/kernel/arch/x86/ioapic.cpp | 2 +- .../kernel/arch/x86/timers/x86_hpet.cpp | 2 +- src/system/kernel/debug/debug.cpp | 4 +- .../kernel/debug/frame_buffer_console.cpp | 2 +- src/system/kernel/fs/vfs_boot.cpp | 2 +- 21 files changed, 174 insertions(+), 41 deletions(-) create mode 100644 headers/private/kernel/util/FixedWidthPointer.h diff --git a/headers/private/kernel/arch/x86/arch_kernel_args.h b/headers/private/kernel/arch/x86/arch_kernel_args.h index 0949d48726..de17c7ced6 100644 --- a/headers/private/kernel/arch/x86/arch_kernel_args.h +++ b/headers/private/kernel/arch/x86/arch_kernel_args.h @@ -9,6 +9,10 @@ # error This file is included from only #endif + +#include + + #define MAX_BOOT_PTABLES 4 #define _PACKED __attribute__((packed)) @@ -34,14 +38,13 @@ typedef struct { // smp stuff uint32 apic_time_cv_factor; // apic ticks per second uint32 apic_phys; - uint32 *apic; + FixedWidthPointer apic; uint32 ioapic_phys; - uint32 *ioapic; uint32 cpu_apic_id[MAX_BOOT_CPUS]; uint32 cpu_apic_version[MAX_BOOT_CPUS]; // hpet stuff uint32 hpet_phys; - uint32 *hpet; -} arch_kernel_args; + FixedWidthPointer hpet; +} _PACKED arch_kernel_args; #endif /* KERNEL_ARCH_x86_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/boot/addr_range.h b/headers/private/kernel/boot/addr_range.h index 67129eb452..ae46b3cb53 100644 --- a/headers/private/kernel/boot/addr_range.h +++ b/headers/private/kernel/boot/addr_range.h @@ -13,13 +13,13 @@ typedef struct addr_range { uint64 start; uint64 size; -} addr_range; +} _PACKED addr_range; typedef struct phys_addr_range { phys_addr_t start; phys_size_t size; -} phys_addr_range; +} _PACKED phys_addr_range; #ifdef __cplusplus diff --git a/headers/private/kernel/boot/driver_settings.h b/headers/private/kernel/boot/driver_settings.h index 6a30b34277..bee57df92e 100644 --- a/headers/private/kernel/boot/driver_settings.h +++ b/headers/private/kernel/boot/driver_settings.h @@ -6,11 +6,12 @@ #define KERNEL_BOOT_DRIVER_SETTINGS_H +#include #include struct driver_settings_file { - struct driver_settings_file *next; + FixedWidthPointer next; char name[B_OS_NAME_LENGTH]; char *buffer; size_t size; diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index d825d440a7..3cc17049d4 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -9,10 +9,11 @@ #include #include #include +#include struct preloaded_image { - struct preloaded_image *next; + FixedWidthPointer next; char *name; elf_region text_region; elf_region data_region; @@ -37,7 +38,7 @@ struct preloaded_image { // the ID field will be filled out in the kernel bool is_module; // set by the module initialization code -}; +} _PACKED; #ifdef __cplusplus extern "C" { diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index 1922ae673d..bc206779ff 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -18,6 +18,9 @@ #include #include +#include + + #define CURRENT_KERNEL_ARGS_VERSION 1 #define MAX_KERNEL_ARGS_RANGE 20 @@ -42,7 +45,7 @@ typedef struct kernel_args { uint32 version; struct preloaded_image kernel_image; - struct preloaded_image *preloaded_images; + FixedWidthPointer preloaded_images; uint32 num_physical_memory_ranges; phys_addr_range physical_memory_range[MAX_PHYSICAL_MEMORY_RANGE]; @@ -58,10 +61,10 @@ typedef struct kernel_args { addr_range cpu_kstack[MAX_BOOT_CPUS]; // boot volume KMessage data - uint64 boot_volume; + FixedWidthPointer boot_volume; int32 boot_volume_size; - struct driver_settings_file *driver_settings; + FixedWidthPointer driver_settings; struct { phys_addr_range physical_buffer; @@ -72,12 +75,12 @@ typedef struct kernel_args { bool enabled; } frame_buffer; - void *vesa_modes; + FixedWidthPointer vesa_modes; uint16 vesa_modes_size; uint8 vesa_capabilities; - void *edid_info; + FixedWidthPointer edid_info; - void *debug_output; + FixedWidthPointer debug_output; uint32 debug_size; bool keep_debug_output_buffer; @@ -85,8 +88,8 @@ typedef struct kernel_args { arch_kernel_args arch_args; // bootsplash data - uint8 *boot_splash; + FixedWidthPointer boot_splash; -} kernel_args; +} _PACKED kernel_args; #endif /* KERNEL_BOOT_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h index 1b0ff82075..a191a0db14 100644 --- a/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h +++ b/headers/private/kernel/boot/platform/bios_ia32/platform_kernel_args.h @@ -12,6 +12,7 @@ #include #include +#include // must match SMP_MAX_CPUS in arch_smp.h @@ -25,9 +26,10 @@ typedef struct { uint16 serial_base_ports[MAX_SERIAL_PORTS]; - bios_drive *drives; // this does not contain the boot drive + FixedWidthPointer drives; + // this does not contain the boot drive apm_info apm; -} platform_kernel_args; +} _PACKED platform_kernel_args; #endif /* KERNEL_BOOT_PLATFORM_BIOS_IA32_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/util/FixedWidthPointer.h b/headers/private/kernel/util/FixedWidthPointer.h new file mode 100644 index 0000000000..b8ceaaf0af --- /dev/null +++ b/headers/private/kernel/util/FixedWidthPointer.h @@ -0,0 +1,123 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_UTIL_FIXED_WIDTH_POINTER_H +#define KERNEL_UTIL_FIXED_WIDTH_POINTER_H + + +#include + + +/*! + \class FixedWidthPointer + \brief Pointer class with fixed size (64-bit) storage. + + This class is a pointer-like class that uses a fixed size 64-bit storage. + This is used to make kernel_args compatible (i.e. the same size) for both + 32-bit and 64-bit kernels. +*/ +template +class FixedWidthPointer { +public: + operator Type*() const + { + return (Type *)(addr_t)fValue; + } + + operator addr_t() const + { + return (addr_t)fValue; + } + + Type &operator*() const + { + return *(Type *)*this; + } + + Type *operator->() const + { + return *this; + } + + FixedWidthPointer &operator=(const FixedWidthPointer &p) + { + fValue = p.fValue; + return *this; + } + + FixedWidthPointer &operator=(Type *p) + { + fValue = (addr_t)p; + return *this; + } + + /*! + Get the 64-bit pointer value. + \return Pointer address. + */ + uint64 Get() const + { + return fValue; + } + + /*! + Set the 64-bit pointer value. + \param addr New address for the pointer. + */ + void SetTo(uint64 addr) + { + fValue = addr; + } +private: + uint64 fValue; +} _PACKED; + + +// Specialization for void pointers, can be converted to another pointer type. +template<> +class FixedWidthPointer { +public: + operator void*() const + { + return (void *)(addr_t)fValue; + } + + template + operator OtherType*() const + { + return (OtherType *)(addr_t)fValue; + } + + operator addr_t() const + { + return (addr_t)fValue; + } + + FixedWidthPointer &operator=(const FixedWidthPointer &p) + { + fValue = p.fValue; + return *this; + } + + FixedWidthPointer &operator=(void *p) + { + fValue = (addr_t)p; + return *this; + } + + uint64 Get() const + { + return fValue; + } + + void SetTo(uint64 addr) + { + fValue = addr; + } +private: + uint64 fValue; +} _PACKED; + + +#endif /* KERNEL_UTIL_FIXED_WIDTH_POINTER_H */ diff --git a/src/system/boot/loader/main.cpp b/src/system/boot/loader/main.cpp index 2af8c86316..63a78a1e9a 100644 --- a/src/system/boot/loader/main.cpp +++ b/src/system/boot/loader/main.cpp @@ -128,7 +128,7 @@ main(stage2_args *args) buffer = (void*)(((addr_t)buffer + 3) & ~(addr_t)0x3); memcpy(buffer, gBootVolume.Buffer(), gBootVolume.ContentSize()); - gKernelArgs.boot_volume = (addr_t)buffer; + gKernelArgs.boot_volume = buffer; gKernelArgs.boot_volume_size = gBootVolume.ContentSize(); // ToDo: cleanup, heap_release() etc. diff --git a/src/system/boot/platform/bios_ia32/debug.cpp b/src/system/boot/platform/bios_ia32/debug.cpp index 73d2906415..deb389dce5 100644 --- a/src/system/boot/platform/bios_ia32/debug.cpp +++ b/src/system/boot/platform/bios_ia32/debug.cpp @@ -162,7 +162,7 @@ debug_cleanup(void) if (!gKernelArgs.keep_debug_output_buffer) { gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); - if (gKernelArgs.debug_output != NULL) { + if (gKernelArgs.debug_output) { memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); gKernelArgs.debug_size = sBufferPosition; } diff --git a/src/system/boot/platform/bios_ia32/hpet.cpp b/src/system/boot/platform/bios_ia32/hpet.cpp index 42568d214b..de27385b33 100644 --- a/src/system/boot/platform/bios_ia32/hpet.cpp +++ b/src/system/boot/platform/bios_ia32/hpet.cpp @@ -50,6 +50,6 @@ hpet_init(void) TRACE(("hpet_init: found HPET at %x.\n", hpet->hpet_address.address)); gKernelArgs.arch_args.hpet_phys = hpet->hpet_address.address; - gKernelArgs.arch_args.hpet = (uint32 *)mmu_map_physical_memory( + gKernelArgs.arch_args.hpet = (void *)mmu_map_physical_memory( gKernelArgs.arch_args.hpet_phys, B_PAGE_SIZE, kDefaultPageFlags); } diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index fcc1bb640b..f31af15f2a 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -60,21 +60,21 @@ static int smp_get_current_cpu(void); static uint32 apic_read(uint32 offset) { - return *(volatile uint32 *)((uint32)gKernelArgs.arch_args.apic + offset); + return *(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic + offset); } static void apic_write(uint32 offset, uint32 data) { - *(volatile uint32 *)((uint32)gKernelArgs.arch_args.apic + offset) = data; + *(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic + offset) = data; } static int smp_get_current_cpu(void) { - if (gKernelArgs.arch_args.apic == NULL) + if (!gKernelArgs.arch_args.apic) return 0; uint8 apicID = apic_read(APIC_ID) >> 24; @@ -451,10 +451,10 @@ smp_init_other_cpus(void) (void *)gKernelArgs.arch_args.ioapic_phys)); // map in the apic - gKernelArgs.arch_args.apic = (uint32 *)mmu_map_physical_memory( + gKernelArgs.arch_args.apic = (void *)mmu_map_physical_memory( gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags); - TRACE(("smp: apic (mapped) = %p\n", gKernelArgs.arch_args.apic)); + TRACE(("smp: apic (mapped) = %p\n", (void *)gKernelArgs.arch_args.apic)); // calculate how fast the apic timer is calculate_apic_timer_conversion_factor(); diff --git a/src/system/boot/platform/bios_ia32/video.cpp b/src/system/boot/platform/bios_ia32/video.cpp index fa9b1fba8c..be634ff29a 100644 --- a/src/system/boot/platform/bios_ia32/video.cpp +++ b/src/system/boot/platform/bios_ia32/video.cpp @@ -957,7 +957,7 @@ platform_init_video(void) } gKernelArgs.edid_info = kernel_args_malloc(sizeof(edid1_info)); - if (gKernelArgs.edid_info != NULL) + if (gKernelArgs.edid_info) memcpy(gKernelArgs.edid_info, &info, sizeof(edid1_info)); } diff --git a/src/system/boot/platform/generic/video_splash.cpp b/src/system/boot/platform/generic/video_splash.cpp index 8d3cb49a8e..ceebb2eab1 100644 --- a/src/system/boot/platform/generic/video_splash.cpp +++ b/src/system/boot/platform/generic/video_splash.cpp @@ -146,12 +146,12 @@ video_display_splash(addr_t frameBuffer) // pointer into the lower half of the icons image data gKernelArgs.boot_splash = (uint8*)kernel_args_malloc(uncompressedSize); - if (gKernelArgs.boot_splash == NULL) + if (!gKernelArgs.boot_splash) return B_NO_MEMORY; uncompress(kSplashIcons8BitCompressedImage, sizeof(kSplashIcons8BitCompressedImage), gKernelArgs.boot_splash, uncompressedSize); - lowerHalfIconImage = gKernelArgs.boot_splash + lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash + (kSplashIconsWidth * iconsHalfHeight); break; default: // 24bits is assumed here @@ -159,12 +159,12 @@ video_display_splash(addr_t frameBuffer) // pointer into the lower half of the icons image data gKernelArgs.boot_splash = (uint8*)kernel_args_malloc(uncompressedSize); - if (gKernelArgs.boot_splash == NULL) + if (!gKernelArgs.boot_splash) return B_NO_MEMORY; uncompress(kSplashIcons24BitCompressedImage, sizeof(kSplashIcons24BitCompressedImage), gKernelArgs.boot_splash, uncompressedSize); - lowerHalfIconImage = gKernelArgs.boot_splash + lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash + (kSplashIconsWidth * iconsHalfHeight) * 3; break; } diff --git a/src/system/boot/platform/openfirmware/video.cpp b/src/system/boot/platform/openfirmware/video.cpp index 639723d09b..d996cd9035 100644 --- a/src/system/boot/platform/openfirmware/video.cpp +++ b/src/system/boot/platform/openfirmware/video.cpp @@ -126,7 +126,7 @@ platform_init_video(void) edid_dump(&info); #endif gKernelArgs.edid_info = kernel_args_malloc(sizeof(edid1_info)); - if (gKernelArgs.edid_info != NULL) + if (gKernelArgs.edid_info) memcpy(gKernelArgs.edid_info, &info, sizeof(edid1_info)); } diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index 12c6357d26..4ba65ef26a 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -83,7 +83,7 @@ serial_cleanup(void) return; gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); - if (gKernelArgs.debug_output != NULL) { + if (gKernelArgs.debug_output) { memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); gKernelArgs.debug_size = sBufferPosition; } diff --git a/src/system/kernel/arch/x86/apic.cpp b/src/system/kernel/arch/x86/apic.cpp index 2c83935402..12492003ae 100644 --- a/src/system/kernel/arch/x86/apic.cpp +++ b/src/system/kernel/arch/x86/apic.cpp @@ -68,7 +68,7 @@ apic_disable_local_ints() status_t apic_init(kernel_args *args) { - if (args->arch_args.apic == NULL) + if (!args->arch_args.apic) return B_NO_INIT; sLocalAPIC = args->arch_args.apic; diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index 6d40b1645b..fa23b17571 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -650,7 +650,7 @@ ioapic_init(kernel_args* args) &ioapic_end_of_interrupt }; - if (args->arch_args.apic == NULL) + if (!args->arch_args.apic) return; if (args->arch_args.ioapic_phys == 0) { diff --git a/src/system/kernel/arch/x86/timers/x86_hpet.cpp b/src/system/kernel/arch/x86/timers/x86_hpet.cpp index d5dfa48693..e75a8795e0 100644 --- a/src/system/kernel/arch/x86/timers/x86_hpet.cpp +++ b/src/system/kernel/arch/x86/timers/x86_hpet.cpp @@ -217,7 +217,7 @@ hpet_init(struct kernel_args *args) /* hpet_acpi_probe() through a similar "scan spots" table to that of smp.cpp. Seems to be the most elegant solution right now. */ - if (args->arch_args.hpet == NULL) + if (!args->arch_args.hpet) return B_ERROR; if (sHPETRegs == NULL) { diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 64810c204d..0a4d759dd1 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1401,7 +1401,7 @@ syslog_init_post_vm(struct kernel_args* args) sSyslogMessage->ident[0] = '\0'; //strcpy(sSyslogMessage->ident, "KERNEL"); - if (args->debug_output != NULL) + if (args->debug_output) syslog_write((const char*)args->debug_output, args->debug_size, false); char revisionBuffer[64]; @@ -1431,7 +1431,7 @@ err1: static status_t syslog_init(struct kernel_args* args) { - if (!args->keep_debug_output_buffer || args->debug_output == NULL) + if (!args->keep_debug_output_buffer || !args->debug_output) return B_OK; sSyslogBuffer = create_ring_buffer_etc(args->debug_output, args->debug_size, diff --git a/src/system/kernel/debug/frame_buffer_console.cpp b/src/system/kernel/debug/frame_buffer_console.cpp index 5a1f67d865..205f50d9d5 100644 --- a/src/system/kernel/debug/frame_buffer_console.cpp +++ b/src/system/kernel/debug/frame_buffer_console.cpp @@ -442,7 +442,7 @@ frame_buffer_console_init(kernel_args* args) add_boot_item(VESA_MODES_BOOT_INFO, sVesaModes, args->vesa_modes_size); } - if (args->edid_info != NULL) { + if (args->edid_info) { edid1_info* info = (edid1_info*)malloc(sizeof(edid1_info)); if (info != NULL) { memcpy(info, args->edid_info, sizeof(edid1_info)); diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index ac039fb0be..b8240d71f2 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -325,7 +325,7 @@ static status_t get_boot_partitions(kernel_args* args, PartitionStack& partitions) { KMessage bootVolume; - bootVolume.SetTo((void *)(addr_t)args->boot_volume, args->boot_volume_size); + bootVolume.SetTo(args->boot_volume, args->boot_volume_size); dprintf("get_boot_partitions(): boot volume message:\n"); bootVolume.Dump(&dprintf); From 5915eeb461026dabc5e2ccd61b650cd7fc0e40a7 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 21 Jun 2012 19:45:36 +0100 Subject: [PATCH 023/273] Some improvements to the previous changes made to vfs_boot.cpp suggested by Ingo. --- src/system/kernel/fs/vfs_boot.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index b8240d71f2..c01a132c82 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -54,8 +54,6 @@ static struct { {NULL} }; -static int32 sBootMethodType; - // This can be used by other code to see if there is a boot file system already dev_t gBootDevice = -1; bool gReadOnlyBootDevice = false; @@ -322,30 +320,27 @@ DiskBootMethod::SortPartitions(KPartition** partitions, int32 count) The boot code should then just try them one by one. */ static status_t -get_boot_partitions(kernel_args* args, PartitionStack& partitions) +get_boot_partitions(KMessage &bootVolume, PartitionStack& partitions) { - KMessage bootVolume; - bootVolume.SetTo(args->boot_volume, args->boot_volume_size); - dprintf("get_boot_partitions(): boot volume message:\n"); bootVolume.Dump(&dprintf); // create boot method - sBootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); + int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); dprintf("get_boot_partitions(): boot method type: %" B_PRId32 "\n", - sBootMethodType); + bootMethodType); BootMethod* bootMethod = NULL; - switch (sBootMethodType) { + switch (bootMethodType) { case BOOT_METHOD_NET: - bootMethod = new(nothrow) NetBootMethod(bootVolume, sBootMethodType); + bootMethod = new(nothrow) NetBootMethod(bootVolume, bootMethodType); break; case BOOT_METHOD_HARD_DISK: case BOOT_METHOD_CD: default: bootMethod = new(nothrow) DiskBootMethod(bootVolume, - sBootMethodType); + bootMethodType); break; } @@ -464,8 +459,11 @@ vfs_bootstrap_file_systems(void) void vfs_mount_boot_file_system(kernel_args* args) { + KMessage bootVolume; + bootVolume.SetTo(args->boot_volume, args->boot_volume_size); + PartitionStack partitions; - status_t status = get_boot_partitions(args, partitions); + status_t status = get_boot_partitions(bootVolume, partitions); if (status < B_OK) { panic("get_boot_partitions failed!"); } @@ -516,8 +514,9 @@ vfs_mount_boot_file_system(kernel_args* args) // whether the module images the boot loader has pre-loaded are the same as // on the boot volume. That is the case when booting from hard disk or CD, // but not via network. - bool bootingFromBootLoaderVolume = sBootMethodType == BOOT_METHOD_HARD_DISK - || sBootMethodType == BOOT_METHOD_CD; + int32 bootMethodType = bootVolume.GetInt32(BOOT_METHOD, BOOT_METHOD_DEFAULT); + bool bootingFromBootLoaderVolume = bootMethodType == BOOT_METHOD_HARD_DISK + || bootMethodType == BOOT_METHOD_CD; module_init_post_boot_device(bootingFromBootLoaderVolume); file_cache_init_post_boot_device(); From 17a3389882cee19532ddc99bc1f9aa1efd296749 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 21 Jun 2012 19:48:03 +0100 Subject: [PATCH 024/273] Remove phys_addr_range, just use addr_range for both virtual and physical address ranges (as requested by Ingo). --- headers/private/kernel/boot/addr_range.h | 20 +- headers/private/kernel/boot/kernel_args.h | 20 +- src/system/boot/arch/m68k/mmu.cpp | 16 +- src/system/boot/loader/kernel_args.cpp | 232 +++++------------- src/system/boot/loader/menu.cpp | 4 +- src/system/boot/platform/amiga_m68k/mmu.cpp | 16 +- src/system/boot/platform/atari_m68k/mmu.cpp | 16 +- src/system/boot/platform/bios_ia32/mmu.cpp | 29 ++- src/system/boot/platform/cfe/arch/ppc/mmu.cpp | 14 +- .../platform/openfirmware/arch/ppc/mmu.cpp | 14 +- .../arch/arm/arch_vm_translation_map.cpp | 2 +- .../arch/m68k/arch_vm_translation_map.cpp | 2 +- .../arch/x86/arch_vm_translation_map.cpp | 2 +- 13 files changed, 145 insertions(+), 242 deletions(-) diff --git a/headers/private/kernel/boot/addr_range.h b/headers/private/kernel/boot/addr_range.h index ae46b3cb53..80d0c7823f 100644 --- a/headers/private/kernel/boot/addr_range.h +++ b/headers/private/kernel/boot/addr_range.h @@ -16,12 +16,6 @@ typedef struct addr_range { } _PACKED addr_range; -typedef struct phys_addr_range { - phys_addr_t start; - phys_size_t size; -} _PACKED phys_addr_range; - - #ifdef __cplusplus extern "C" { #endif @@ -36,18 +30,8 @@ bool is_address_range_covered(addr_range* ranges, uint32 numRanges, uint64 base, uint64 size); void sort_address_ranges(addr_range* ranges, uint32 numRanges); -status_t insert_physical_address_range(phys_addr_range* ranges, - uint32* _numRanges, uint32 maxRanges, phys_addr_t start, phys_size_t size); -status_t remove_physical_address_range(phys_addr_range* ranges, - uint32* _numRanges, uint32 maxRanges, phys_addr_t start, phys_size_t size); -bool get_free_physical_address_range(phys_addr_range* ranges, uint32 numRanges, - phys_addr_t base, phys_size_t size, phys_addr_t* _rangeBase); -bool is_physical_address_range_covered(phys_addr_range* ranges, - uint32 numRanges, phys_addr_t base, phys_size_t size); -void sort_physical_address_ranges(phys_addr_range* ranges, uint32 numRanges); - -status_t insert_physical_memory_range(phys_addr_t start, phys_size_t size); -status_t insert_physical_allocated_range(phys_addr_t start, phys_size_t size); +status_t insert_physical_memory_range(uint64 start, uint64 size); +status_t insert_physical_allocated_range(uint64 start, uint64 size); status_t insert_virtual_allocated_range(uint64 start, uint64 size); void ignore_physical_memory_ranges_beyond_4gb(); diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index bc206779ff..b2e7ee93fb 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -47,15 +47,15 @@ typedef struct kernel_args { struct preloaded_image kernel_image; FixedWidthPointer preloaded_images; - uint32 num_physical_memory_ranges; - phys_addr_range physical_memory_range[MAX_PHYSICAL_MEMORY_RANGE]; - uint32 num_physical_allocated_ranges; - phys_addr_range physical_allocated_range[MAX_PHYSICAL_ALLOCATED_RANGE]; - uint32 num_virtual_allocated_ranges; - addr_range virtual_allocated_range[MAX_VIRTUAL_ALLOCATED_RANGE]; - uint32 num_kernel_args_ranges; - addr_range kernel_args_range[MAX_KERNEL_ARGS_RANGE]; - uint64 ignored_physical_memory; + uint32 num_physical_memory_ranges; + addr_range physical_memory_range[MAX_PHYSICAL_MEMORY_RANGE]; + uint32 num_physical_allocated_ranges; + addr_range physical_allocated_range[MAX_PHYSICAL_ALLOCATED_RANGE]; + uint32 num_virtual_allocated_ranges; + addr_range virtual_allocated_range[MAX_VIRTUAL_ALLOCATED_RANGE]; + uint32 num_kernel_args_ranges; + addr_range kernel_args_range[MAX_KERNEL_ARGS_RANGE]; + uint64 ignored_physical_memory; uint32 num_cpus; addr_range cpu_kstack[MAX_BOOT_CPUS]; @@ -67,7 +67,7 @@ typedef struct kernel_args { FixedWidthPointer driver_settings; struct { - phys_addr_range physical_buffer; + addr_range physical_buffer; uint32 bytes_per_row; uint16 width; uint16 height; diff --git a/src/system/boot/arch/m68k/mmu.cpp b/src/system/boot/arch/m68k/mmu.cpp index 776fd99e1f..b7c2526d4a 100644 --- a/src/system/boot/arch/m68k/mmu.cpp +++ b/src/system/boot/arch/m68k/mmu.cpp @@ -503,9 +503,9 @@ mmu_init_for_kernel(void) gKernelArgs.num_virtual_allocated_ranges = 1; // sort the address ranges - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); - sort_physical_address_ranges(gKernelArgs.physical_allocated_range, + sort_address_ranges(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges); sort_address_ranges(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges); @@ -516,17 +516,23 @@ mmu_init_for_kernel(void) dprintf("phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_memory_range[i].start, gKernelArgs.physical_memory_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_memory_range[i].start, + gKernelArgs.physical_memory_range[i].size); } dprintf("allocated phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_allocated_range[i].start, gKernelArgs.physical_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_allocated_range[i].start, + gKernelArgs.physical_allocated_range[i].size); } dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.virtual_allocated_range[i].start, + gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/loader/kernel_args.cpp b/src/system/boot/loader/kernel_args.cpp index 0de1205a7e..d625728cf4 100644 --- a/src/system/boot/loader/kernel_args.cpp +++ b/src/system/boot/loader/kernel_args.cpp @@ -26,9 +26,20 @@ static void* sLast; static size_t sFree = kChunkSize; -template +static status_t +add_kernel_args_range(void* start, size_t size) +{ + return insert_address_range(gKernelArgs.kernel_args_range, + &gKernelArgs.num_kernel_args_ranges, MAX_KERNEL_ARGS_RANGE, + (addr_t)start, size); +} + + +// #pragma mark - addr_range utility functions + + static void -remove_range_index(RangeType* ranges, uint32& numRanges, uint32 index) +remove_range_index(addr_range* ranges, uint32& numRanges, uint32 index) { if (index + 1 == numRanges) { // remove last range @@ -37,25 +48,31 @@ remove_range_index(RangeType* ranges, uint32& numRanges, uint32 index) } memmove(&ranges[index], &ranges[index + 1], - sizeof(RangeType) * (numRanges - 1 - index)); + sizeof(addr_range) * (numRanges - 1 - index)); numRanges--; } -template -static status_t -insert_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, - AddressType start, SizeType size) +/*! Inserts the specified (start, size) pair (aka range) in the + addr_range array. + It will extend existing ranges in order to have as little + ranges in the array as possible. + Returns B_OK on success, or B_ENTRY_NOT_FOUND if there was + no free array entry available anymore. +*/ +extern "C" status_t +insert_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, + uint64 start, uint64 size) { uint32 numRanges = *_numRanges; start = ROUNDDOWN(start, B_PAGE_SIZE); size = ROUNDUP(size, B_PAGE_SIZE); - AddressType end = start + size; + uint64 end = start + size; for (uint32 i = 0; i < numRanges; i++) { - AddressType rangeStart = ranges[i].start; - AddressType rangeEnd = rangeStart + ranges[i].size; + uint64 rangeStart = ranges[i].start; + uint64 rangeEnd = rangeStart + ranges[i].size; if (end < rangeStart || start > rangeEnd) { // ranges don't intersect or touch each other @@ -84,8 +101,8 @@ insert_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, rangeStart = ranges[i].start; rangeEnd = rangeStart + ranges[i].size; - AddressType joinStart = ranges[j].start; - AddressType joinEnd = joinStart + ranges[j].size; + uint64 joinStart = ranges[j].start; + uint64 joinEnd = joinStart + ranges[j].size; if (rangeStart <= joinEnd && joinEnd <= rangeEnd) { // join range that used to be before the current one, or @@ -113,7 +130,7 @@ insert_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, if (numRanges >= maxRanges) return B_ENTRY_NOT_FOUND; - ranges[numRanges].start = (AddressType)start; + ranges[numRanges].start = (uint64)start; ranges[numRanges].size = size; (*_numRanges)++; @@ -121,19 +138,18 @@ insert_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, } -template -static status_t -remove_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, - AddressType start, SizeType size) +extern "C" status_t +remove_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, + uint64 start, uint64 size) { uint32 numRanges = *_numRanges; - AddressType end = ROUNDUP(start + size, B_PAGE_SIZE); + uint64 end = ROUNDUP(start + size, B_PAGE_SIZE); start = ROUNDDOWN(start, B_PAGE_SIZE); for (uint32 i = 0; i < numRanges; i++) { - AddressType rangeStart = ranges[i].start; - AddressType rangeEnd = rangeStart + ranges[i].size; + uint64 rangeStart = ranges[i].start; + uint64 rangeEnd = rangeStart + ranges[i].size; if (start <= rangeStart) { if (end <= rangeStart) { @@ -158,8 +174,8 @@ remove_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, // the range. We keep the head of the range and insert its tail // as a new range. ranges[i].size = start - rangeStart; - return insert_range(ranges, - _numRanges, maxRanges, end, rangeEnd - end); + return insert_address_range(ranges, _numRanges, maxRanges, end, + rangeEnd - end); } } @@ -168,12 +184,11 @@ remove_range(RangeType* ranges, uint32* _numRanges, uint32 maxRanges, } -template -static bool -get_free_range(RangeType* ranges, uint32 numRanges, AddressType base, - SizeType size, AddressType* _rangeBase) +bool +get_free_address_range(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size, uint64* _rangeBase) { - AddressType end = base + size - 1; + uint64 end = base + size - 1; if (end < base) return false; @@ -182,8 +197,8 @@ get_free_range(RangeType* ranges, uint32 numRanges, AddressType base, // intersects with an existing one. for (uint32 i = 0; i < numRanges;) { - AddressType rangeStart = ranges[i].start; - AddressType rangeEnd = ranges[i].start + ranges[i].size - 1; + uint64 rangeStart = ranges[i].start; + uint64 rangeEnd = ranges[i].start + ranges[i].size - 1; if (base <= rangeEnd && rangeStart <= end) { base = rangeEnd + 1; @@ -203,21 +218,20 @@ get_free_range(RangeType* ranges, uint32 numRanges, AddressType base, } -template -static bool -is_range_covered(RangeType* ranges, uint32 numRanges, AddressType base, - SizeType size) +bool +is_address_range_covered(addr_range* ranges, uint32 numRanges, uint64 base, + uint64 size) { // Note: We don't assume that the ranges are sorted, so we can't do this // in a simple loop. Instead we restart the loop whenever the start of the // given range intersects with an existing one. for (uint32 i = 0; i < numRanges;) { - AddressType rangeStart = ranges[i].start; - AddressType rangeSize = ranges[i].size; + uint64 rangeStart = ranges[i].start; + uint64 rangeSize = ranges[i].size; if (rangeStart <= base && rangeSize > base - rangeStart) { - SizeType intersect = std::min(rangeStart + rangeSize - base, size); + uint64 intersect = std::min(rangeStart + rangeSize - base, size); base += intersect; size -= intersect; if (size == 0) @@ -234,155 +248,43 @@ is_range_covered(RangeType* ranges, uint32 numRanges, AddressType base, } -template -static void -sort_ranges(RangeType* ranges, uint32 count) +void +sort_address_ranges(addr_range* ranges, uint32 numRanges) { // TODO: This is a pretty sucky bubble sort implementation! bool done; do { done = true; - for (uint32 i = 1; i < count; i++) { + for (uint32 i = 1; i < numRanges; i++) { if (ranges[i].start < ranges[i - 1].start) { done = false; - RangeType tempRange; - memcpy(&tempRange, &ranges[i], sizeof(RangeType)); - memcpy(&ranges[i], &ranges[i - 1], sizeof(RangeType)); - memcpy(&ranges[i - 1], &tempRange, sizeof(RangeType)); + addr_range tempRange; + memcpy(&tempRange, &ranges[i], sizeof(addr_range)); + memcpy(&ranges[i], &ranges[i - 1], sizeof(addr_range)); + memcpy(&ranges[i - 1], &tempRange, sizeof(addr_range)); } } } while (!done); } -// #pragma mark - - - -static status_t -add_kernel_args_range(void* start, size_t size) -{ - return insert_address_range(gKernelArgs.kernel_args_range, - &gKernelArgs.num_kernel_args_ranges, MAX_KERNEL_ARGS_RANGE, - (addr_t)start, size); -} - - -// #pragma mark - addr_range utility functions - - -/*! Inserts the specified (start, size) pair (aka range) in the - addr_range array. - It will extend existing ranges in order to have as little - ranges in the array as possible. - Returns B_OK on success, or B_ENTRY_NOT_FOUND if there was - no free array entry available anymore. -*/ -extern "C" status_t -insert_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, - uint64 start, uint64 size) -{ - return insert_range(ranges, _numRanges, - maxRanges, start, size); -} - - -extern "C" status_t -remove_address_range(addr_range* ranges, uint32* _numRanges, uint32 maxRanges, - uint64 start, uint64 size) -{ - return remove_range(ranges, _numRanges, - maxRanges, start, size); -} - - -bool -get_free_address_range(addr_range* ranges, uint32 numRanges, uint64 base, - uint64 size, uint64* _rangeBase) -{ - return get_free_range(ranges, numRanges, base, - size, _rangeBase); -} - - -bool -is_address_range_covered(addr_range* ranges, uint32 numRanges, uint64 base, - uint64 size) -{ - return is_range_covered(ranges, numRanges, base, - size); -} - - -void -sort_address_ranges(addr_range* ranges, uint32 numRanges) -{ - sort_ranges(ranges, numRanges); -} - - -// #pragma mark - phys_addr_range utility functions - - -status_t -insert_physical_address_range(phys_addr_range* ranges, uint32* _numRanges, - uint32 maxRanges, phys_addr_t start, phys_size_t size) -{ - return insert_range(ranges, - _numRanges, maxRanges, start, size); -} - - -status_t -remove_physical_address_range(phys_addr_range* ranges, uint32* _numRanges, - uint32 maxRanges, phys_addr_t start, phys_size_t size) -{ - return remove_range(ranges, - _numRanges, maxRanges, start, size); -} - - -bool -get_free_physical_address_range(phys_addr_range* ranges, uint32 numRanges, - phys_addr_t base, phys_size_t size, phys_addr_t* _rangeBase) -{ - return get_free_range(ranges, - numRanges, base, size, _rangeBase); -} - - -bool -is_physical_address_range_covered(phys_addr_range* ranges, uint32 numRanges, - phys_addr_t base, phys_size_t size) -{ - return is_range_covered(ranges, - numRanges, base, size); -} - - -void -sort_physical_address_ranges(phys_addr_range* ranges, uint32 numRanges) -{ - sort_ranges(ranges, numRanges); -} - - // #pragma mark - kernel args range functions status_t -insert_physical_memory_range(phys_addr_t start, phys_size_t size) +insert_physical_memory_range(uint64 start, uint64 size) { - return insert_physical_address_range(gKernelArgs.physical_memory_range, + return insert_address_range(gKernelArgs.physical_memory_range, &gKernelArgs.num_physical_memory_ranges, MAX_PHYSICAL_MEMORY_RANGE, start, size); } status_t -insert_physical_allocated_range(phys_addr_t start, phys_size_t size) +insert_physical_allocated_range(uint64 start, uint64 size) { - return insert_physical_address_range(gKernelArgs.physical_allocated_range, + return insert_address_range(gKernelArgs.physical_allocated_range, &gKernelArgs.num_physical_allocated_ranges, MAX_PHYSICAL_ALLOCATED_RANGE, start, size); } @@ -403,19 +305,19 @@ void ignore_physical_memory_ranges_beyond_4gb() { // sort - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); - static const phys_addr_t kLimit = (phys_addr_t)1 << 32; + static const uint64 kLimit = (uint64)1 << 32; // remove everything past 4 GB for (uint32 i = gKernelArgs.num_physical_memory_ranges; i > 0; i--) { - phys_addr_range& range = gKernelArgs.physical_memory_range[i - 1]; + addr_range& range = gKernelArgs.physical_memory_range[i - 1]; if (range.start >= kLimit) { // the complete range is beyond the limit dprintf("ignore_physical_memory_ranges_beyond_4gb(): ignoring " - "range: %#" B_PRIxPHYSADDR " - %#" B_PRIxPHYSADDR "\n", - range.start, range.start + range.size); + "range: %#" B_PRIx64 " - %#" B_PRIx64 "\n", range.start, + range.start + range.size); gKernelArgs.ignored_physical_memory += range.size; gKernelArgs.num_physical_memory_ranges = i - 1; continue; @@ -424,7 +326,7 @@ ignore_physical_memory_ranges_beyond_4gb() if (kLimit - range.start < range.size) { // the range is partially beyond the limit dprintf("ignore_physical_memory_ranges_beyond_4gb(): ignoring " - "range: %#" B_PRIxPHYSADDR " - %#" B_PRIxPHYSADDR "\n", kLimit, + "range: %#" B_PRIx64 " - %#" B_PRIx64 "\n", kLimit, range.start + range.size); gKernelArgs.ignored_physical_memory += range.size - (kLimit - range.start); diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index e0f6b2b138..0397237359 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -747,8 +747,8 @@ add_safe_mode_menu() // check whether we have memory beyond 4 GB bool hasMemoryBeyond4GB = false; for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { - phys_addr_range& range = gKernelArgs.physical_memory_range[i]; - if (range.start >= (phys_addr_t)1 << 32) { + addr_range& range = gKernelArgs.physical_memory_range[i]; + if (range.start >= (uint64)1 << 32) { hasMemoryBeyond4GB = true; break; } diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp b/src/system/boot/platform/amiga_m68k/mmu.cpp index 230b967f38..03f56b9f4e 100644 --- a/src/system/boot/platform/amiga_m68k/mmu.cpp +++ b/src/system/boot/platform/amiga_m68k/mmu.cpp @@ -503,9 +503,9 @@ mmu_init_for_kernel(void) gKernelArgs.num_virtual_allocated_ranges = 1; // sort the address ranges - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); - sort_physical_address_ranges(gKernelArgs.physical_allocated_range, + sort_address_ranges(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges); sort_address_ranges(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges); @@ -516,17 +516,23 @@ mmu_init_for_kernel(void) dprintf("phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_memory_range[i].start, gKernelArgs.physical_memory_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_memory_range[i].start, + gKernelArgs.physical_memory_range[i].size); } dprintf("allocated phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_allocated_range[i].start, gKernelArgs.physical_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_allocated_range[i].start, + gKernelArgs.physical_allocated_range[i].size); } dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.virtual_allocated_range[i].start, + gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp b/src/system/boot/platform/atari_m68k/mmu.cpp index 404886bd2a..7132119fd2 100644 --- a/src/system/boot/platform/atari_m68k/mmu.cpp +++ b/src/system/boot/platform/atari_m68k/mmu.cpp @@ -503,9 +503,9 @@ mmu_init_for_kernel(void) gKernelArgs.num_virtual_allocated_ranges = 1; // sort the address ranges - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); - sort_physical_address_ranges(gKernelArgs.physical_allocated_range, + sort_address_ranges(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges); sort_address_ranges(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges); @@ -516,17 +516,23 @@ mmu_init_for_kernel(void) dprintf("phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_memory_range[i].start, gKernelArgs.physical_memory_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_memory_range[i].start, + gKernelArgs.physical_memory_range[i].size); } dprintf("allocated phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - dprintf(" base 0x%08lx, length 0x%08lx\n", gKernelArgs.physical_allocated_range[i].start, gKernelArgs.physical_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.physical_allocated_range[i].start, + gKernelArgs.physical_allocated_range[i].size); } dprintf("allocated virt memory ranges:\n"); for (i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); + dprintf(" base 0x%08" B_PRIx64 ", length 0x%08" B_PRIx64 "\n", + gKernelArgs.virtual_allocated_range[i].start, + gKernelArgs.virtual_allocated_range[i].size); } } #endif diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 4c6a0c8423..cfed3de612 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -108,8 +108,8 @@ get_next_virtual_address(size_t size) static addr_t get_next_physical_address(size_t size) { - phys_addr_t base; - if (!get_free_physical_address_range(gKernelArgs.physical_allocated_range, + uint64 base; + if (!get_free_address_range(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges, sNextPhysicalAddress, size, &base)) { panic("Out of physical memory!"); @@ -426,14 +426,14 @@ bool mmu_allocate_physical(addr_t base, size_t size) { // check whether the physical memory range exists at all - if (!is_physical_address_range_covered(gKernelArgs.physical_memory_range, + if (!is_address_range_covered(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges, base, size)) { return false; } // check whether the physical range is still free - phys_addr_t foundBase; - if (!get_free_physical_address_range(gKernelArgs.physical_allocated_range, + uint64 foundBase; + if (!get_free_address_range(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges, base, size, &foundBase) || foundBase != base) { return false; @@ -565,9 +565,9 @@ mmu_init_for_kernel(void) gKernelArgs.num_virtual_allocated_ranges = 1; // sort the address ranges - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); - sort_physical_address_ranges(gKernelArgs.physical_allocated_range, + sort_address_ranges(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges); sort_address_ranges(gKernelArgs.virtual_allocated_range, gKernelArgs.num_virtual_allocated_ranges); @@ -578,15 +578,14 @@ mmu_init_for_kernel(void) dprintf("phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { - dprintf(" base %#018" B_PRIxPHYSADDR ", length %#018" - B_PRIxPHYSADDR "\n", gKernelArgs.physical_memory_range[i].start, + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.physical_memory_range[i].start, gKernelArgs.physical_memory_range[i].size); } dprintf("allocated phys memory ranges:\n"); for (i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - dprintf(" base %#018" B_PRIxPHYSADDR ", length %#018" - B_PRIxPHYSADDR "\n", + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", gKernelArgs.physical_allocated_range[i].start, gKernelArgs.physical_allocated_range[i].size); } @@ -692,7 +691,7 @@ mmu_init(void) } // sort the ranges - sort_physical_address_ranges(gKernelArgs.physical_memory_range, + sort_address_ranges(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges); // On some machines we get several ranges that contain only a few pages @@ -701,10 +700,10 @@ mmu_init(void) // leave us only with a few larger contiguous ranges (ideally one). for (int32 i = gKernelArgs.num_physical_memory_ranges - 1; i >= 0; i--) { - size_t size = gKernelArgs.physical_memory_range[i].size; + uint64 size = gKernelArgs.physical_memory_range[i].size; if (size < 64 * 1024) { - addr_t start = gKernelArgs.physical_memory_range[i].start; - remove_physical_address_range(gKernelArgs.physical_memory_range, + uint64 start = gKernelArgs.physical_memory_range[i].start; + remove_address_range(gKernelArgs.physical_memory_range, &gKernelArgs.num_physical_memory_ranges, MAX_PHYSICAL_MEMORY_RANGE, start, size); } diff --git a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp index 2f9b2a021d..b20495e59a 100644 --- a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp @@ -98,9 +98,8 @@ is_virtual_allocated(void *address, size_t size) static bool is_physical_allocated(void *address, size_t size) { - phys_addr_t foundBase; - return !get_free_physical_address_range( - gKernelArgs.physical_allocated_range, + uint64 foundBase; + return !get_free_address_range(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges, (addr_t)address, size, &foundBase) || foundBase != (addr_t)address; } @@ -109,7 +108,7 @@ is_physical_allocated(void *address, size_t size) static bool is_physical_memory(void *address, size_t size) { - return is_physical_address_range_covered(gKernelArgs.physical_memory_range, + return is_address_range_covered(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges, (addr_t)address, size); } @@ -243,7 +242,7 @@ find_physical_memory_range(size_t size) { for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { if (gKernelArgs.physical_memory_range[i].size > size) - return (void *)gKernelArgs.physical_memory_range[i].start; + return (void *)(addr_t)gKernelArgs.physical_memory_range[i].start; } return PHYSINVAL; } @@ -262,8 +261,9 @@ find_free_physical_range(size_t size) } for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - void *address = (void *)(gKernelArgs.physical_allocated_range[i].start - + gKernelArgs.physical_allocated_range[i].size); + void *address = + (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + + gKernelArgs.physical_allocated_range[i].size); if (!is_physical_allocated(address, size) && is_physical_memory(address, size)) return address; diff --git a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp index bbe11265ce..7f46272238 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp @@ -180,9 +180,8 @@ is_virtual_allocated(void *address, size_t size) static bool is_physical_allocated(void *address, size_t size) { - phys_addr_t foundBase; - return !get_free_physical_address_range( - gKernelArgs.physical_allocated_range, + uint64 foundBase; + return !get_free_address_range(gKernelArgs.physical_allocated_range, gKernelArgs.num_physical_allocated_ranges, (addr_t)address, size, &foundBase) || foundBase != (addr_t)address; } @@ -191,7 +190,7 @@ is_physical_allocated(void *address, size_t size) static bool is_physical_memory(void *address, size_t size) { - return is_physical_address_range_covered(gKernelArgs.physical_memory_range, + return is_address_range_covered(gKernelArgs.physical_memory_range, gKernelArgs.num_physical_memory_ranges, (addr_t)address, size); } @@ -424,7 +423,7 @@ find_physical_memory_range(size_t size) { for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { if (gKernelArgs.physical_memory_range[i].size > size) - return (void *)gKernelArgs.physical_memory_range[i].start; + return (void *)(addr_t)gKernelArgs.physical_memory_range[i].start; } return PHYSINVAL; } @@ -443,8 +442,9 @@ find_free_physical_range(size_t size) } for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - void *address = (void *)(gKernelArgs.physical_allocated_range[i].start - + gKernelArgs.physical_allocated_range[i].size); + void *address = + (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + + gKernelArgs.physical_allocated_range[i].size); if (!is_physical_allocated(address, size) && is_physical_memory(address, size)) return address; diff --git a/src/system/kernel/arch/arm/arch_vm_translation_map.cpp b/src/system/kernel/arch/arm/arch_vm_translation_map.cpp index 02a042b355..faad4bf263 100644 --- a/src/system/kernel/arch/arm/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/arm/arch_vm_translation_map.cpp @@ -71,7 +71,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); + TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); } #endif diff --git a/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp b/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp index fc211d688a..176f0f11a3 100644 --- a/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/m68k/arch_vm_translation_map.cpp @@ -97,7 +97,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); + TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); } #endif switch (arch_mmu_type) { diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index 7b16d09c43..aa20762e29 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -70,7 +70,7 @@ arch_vm_translation_map_init(kernel_args *args, for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) { addr_t start = args->virtual_allocated_range[i].start; addr_t end = start + args->virtual_allocated_range[i].size; - TRACE(" %#10" B_PRIx64 " - %#10" B_PRIx64 "\n", start, end); + TRACE(" %#10" B_PRIxADDR " - %#10" B_PRIxADDR "\n", start, end); } #endif From 17e407e945f313ed8c2878ad7699ef9384f8a1a0 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 10:53:08 +0100 Subject: [PATCH 025/273] Proper implementation of arch_kernel.h for x86_64. --- .../private/kernel/arch/x86_64/arch_kernel.h | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h index a7e45b34e7..056efafcfa 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel.h @@ -1,6 +1,42 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_ARCH_X86_64_KERNEL_H #define _KERNEL_ARCH_X86_64_KERNEL_H -#include "../x86/arch_kernel.h" + +#ifndef _ASSEMBLER +# include +#endif + + +// Base of the kernel address space. +// When compiling the bootloader, KERNEL_BASE is set to the x86 base address, +// the correct 64-bit addresses are calculated differently. +// For the kernel, this is the base of the kernel address space. This is NOT +// the address where the kernel is loaded to: the kernel is loaded in the top +// 2GB of the virtual address space as required by GCC's kernel code model. +// The whole kernel address space is the top 512GB of the address space. +#ifdef _BOOT_MODE +# define KERNEL_BASE 0x80000000 +#else +# define KERNEL_BASE 0xFFFFFF8000000000 +#endif + +#define KERNEL_SIZE 0x8000000000 +#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) + + +// Userspace address space layout. +#define USER_BASE 0x0 +#define USER_BASE_ANY 0x100000 +#define USER_SIZE 0x800000000000 +#define USER_TOP (USER_BASE + USER_SIZE) + +#define KERNEL_USER_DATA_BASE 0x7FFFEFFF0000 +#define USER_STACK_REGION 0x7FFFF0000000 +#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) + #endif /* _KERNEL_ARCH_X86_64_KERNEL_H */ From 6b87898af5966561770a79a17f13415c47c38aa0 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 11:56:55 +0100 Subject: [PATCH 026/273] Code style fixes. --- .../private/kernel/util/FixedWidthPointer.h | 18 ++++++++++-------- src/system/boot/platform/cfe/arch/ppc/mmu.cpp | 9 +++++---- .../platform/openfirmware/arch/ppc/mmu.cpp | 9 +++++---- src/system/kernel/fs/vfs_boot.cpp | 2 +- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/headers/private/kernel/util/FixedWidthPointer.h b/headers/private/kernel/util/FixedWidthPointer.h index b8ceaaf0af..b6e9662e72 100644 --- a/headers/private/kernel/util/FixedWidthPointer.h +++ b/headers/private/kernel/util/FixedWidthPointer.h @@ -30,23 +30,23 @@ public: return (addr_t)fValue; } - Type &operator*() const + Type& operator*() const { return *(Type *)*this; } - Type *operator->() const + Type* operator->() const { return *this; } - FixedWidthPointer &operator=(const FixedWidthPointer &p) + FixedWidthPointer& operator=(const FixedWidthPointer& p) { fValue = p.fValue; return *this; } - FixedWidthPointer &operator=(Type *p) + FixedWidthPointer& operator=(Type* p) { fValue = (addr_t)p; return *this; @@ -69,6 +69,7 @@ public: { fValue = addr; } + private: uint64 fValue; } _PACKED; @@ -80,13 +81,13 @@ class FixedWidthPointer { public: operator void*() const { - return (void *)(addr_t)fValue; + return (void*)(addr_t)fValue; } template operator OtherType*() const { - return (OtherType *)(addr_t)fValue; + return (OtherType*)(addr_t)fValue; } operator addr_t() const @@ -94,13 +95,13 @@ public: return (addr_t)fValue; } - FixedWidthPointer &operator=(const FixedWidthPointer &p) + FixedWidthPointer& operator=(const FixedWidthPointer& p) { fValue = p.fValue; return *this; } - FixedWidthPointer &operator=(void *p) + FixedWidthPointer& operator=(void* p) { fValue = (addr_t)p; return *this; @@ -115,6 +116,7 @@ public: { fValue = addr; } + private: uint64 fValue; } _PACKED; diff --git a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp index b20495e59a..68c709ee74 100644 --- a/src/system/boot/platform/cfe/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/cfe/arch/ppc/mmu.cpp @@ -261,8 +261,8 @@ find_free_physical_range(size_t size) } for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - void *address = - (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + void *address + = (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + gKernelArgs.physical_allocated_range[i].size); if (!is_physical_allocated(address, size) && is_physical_memory(address, size)) @@ -281,8 +281,9 @@ find_free_virtual_range(void *base, size_t size) void *firstFound = NULL; void *firstBaseFound = NULL; for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - void *address = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start - + gKernelArgs.virtual_allocated_range[i].size); + void *address + = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start + + gKernelArgs.virtual_allocated_range[i].size); if (!is_virtual_allocated(address, size)) { if (!base) return address; diff --git a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp index 7f46272238..a89fec7f53 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp +++ b/src/system/boot/platform/openfirmware/arch/ppc/mmu.cpp @@ -442,8 +442,8 @@ find_free_physical_range(size_t size) } for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { - void *address = - (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + void *address + = (void *)(addr_t)(gKernelArgs.physical_allocated_range[i].start + gKernelArgs.physical_allocated_range[i].size); if (!is_physical_allocated(address, size) && is_physical_memory(address, size)) @@ -462,8 +462,9 @@ find_free_virtual_range(void *base, size_t size) void *firstFound = NULL; void *firstBaseFound = NULL; for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { - void *address = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start - + gKernelArgs.virtual_allocated_range[i].size); + void *address + = (void *)(addr_t)(gKernelArgs.virtual_allocated_range[i].start + + gKernelArgs.virtual_allocated_range[i].size); if (!is_virtual_allocated(address, size)) { if (!base) return address; diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index c01a132c82..21b1b9e627 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -320,7 +320,7 @@ DiskBootMethod::SortPartitions(KPartition** partitions, int32 count) The boot code should then just try them one by one. */ static status_t -get_boot_partitions(KMessage &bootVolume, PartitionStack& partitions) +get_boot_partitions(KMessage& bootVolume, PartitionStack& partitions) { dprintf("get_boot_partitions(): boot volume message:\n"); bootVolume.Dump(&dprintf); From 474aa3b76e4c661c259e2200db895712ded3f9d6 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 12:54:41 +0100 Subject: [PATCH 027/273] Added ELF64 headers, common ELF32 and ELF64 definitions moved to elf_common.h. --- headers/private/system/arch/x86/arch_elf.h | 4 + headers/private/system/arch/x86_64/arch_elf.h | 51 +++- headers/private/system/elf32.h | 234 +-------------- headers/private/system/elf64.h | 239 +++++++++++++++ headers/private/system/elf_common.h | 274 ++++++++++++++++++ 5 files changed, 568 insertions(+), 234 deletions(-) create mode 100644 headers/private/system/elf64.h create mode 100644 headers/private/system/elf_common.h diff --git a/headers/private/system/arch/x86/arch_elf.h b/headers/private/system/arch/x86/arch_elf.h index 4ec86759cb..922ab095a7 100644 --- a/headers/private/system/arch/x86/arch_elf.h +++ b/headers/private/system/arch/x86/arch_elf.h @@ -19,4 +19,8 @@ #define R_386_GOTOFF 9 /* add GOT relative symbol address */ #define R_386_GOTPC 10 /* add PC relative GOT table address */ +#ifdef _BOOT_MODE +# include "../x86_64/arch_elf.h" +#endif + #endif /* _KERNEL_ARCH_x86_ELF_H */ diff --git a/headers/private/system/arch/x86_64/arch_elf.h b/headers/private/system/arch/x86_64/arch_elf.h index 410c003706..6bbba4e5b3 100644 --- a/headers/private/system/arch/x86_64/arch_elf.h +++ b/headers/private/system/arch/x86_64/arch_elf.h @@ -1,6 +1,55 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_ARCH_x86_64_ELF_H #define _KERNEL_ARCH_x86_64_ELF_H -#include "../x86/arch_elf.h" + +/* Relocation types. */ +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Direct 64-bit. */ +#define R_X86_64_PC32 2 /* PC relative 32-bit signed. */ +#define R_X86_64_GOT32 3 /* 32-bit GOT entry. */ +#define R_X86_64_PLT32 4 /* 32-bit PLT address. */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime. */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry. */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry. */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base. */ +#define R_X86_64_GOTPCREL 9 /* 32-bit signed PC relative offset to GOT. */ +#define R_X86_64_32 10 /* Direct 32-bit zero-extended. */ +#define R_X86_64_32S 11 /* Direct 32-bit sign-extended. */ +#define R_X86_64_16 12 /* Direct 16-bit zero-extended. */ +#define R_X86_64_PC16 13 /* 16-bit sign-extended PC relative. */ +#define R_X86_64_8 14 /* Direct 8-bit sign-extended. */ +#define R_X86_64_PC8 15 /* 8-bit sign-extended PC relative. */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol. */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block. */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block. */ +#define R_X86_64_TLSGD 19 /* 32-bit signed PC relative offset to two GOT entries (GD). */ +#define R_X86_64_TLSLD 20 /* 32-bit signed PC relative offset to two GOT entries (LD). */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block. */ +#define R_X86_64_GOTTPOFF 22 /* 32-bit signed PC relative offset to GOT entry (IE). */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block. */ +#define R_X86_64_PC64 24 /* PC relative 64-bit. */ +#define R_X86_64_GOTOFF64 25 /* 64-bit offset to GOT. */ +#define R_X86_64_GOTPC32 26 /* 32 bit signed PC relative offset to GOT. */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset. */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry. */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT. */ +#define R_X86_64_GOTPLT64 30 /* Like GOT64, says PLT entry needed. */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry. */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend. */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend. */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base. */ + + +#ifdef _BOOT_MODE +# include "../x86/arch_elf.h" +#endif + #endif /* _KERNEL_ARCH_x86_64_ELF_H */ diff --git a/headers/private/system/elf32.h b/headers/private/system/elf32.h index 4feee0692b..d9287075df 100644 --- a/headers/private/system/elf32.h +++ b/headers/private/system/elf32.h @@ -9,10 +9,7 @@ #define _ELF32_H -#include -#include - -#include +#include typedef uint32 Elf32_Addr; @@ -25,8 +22,6 @@ typedef Elf32_Half Elf32_Versym; /*** ELF header ***/ -#define EI_NIDENT 16 - struct Elf32_Ehdr { uint8 e_ident[EI_NIDENT]; Elf32_Half e_type; @@ -48,73 +43,6 @@ struct Elf32_Ehdr { #endif }; -#define ELF_MAGIC "\x7f""ELF" - -// e_ident[] indices -#define EI_MAG0 0 -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_PAD 7 - -// e_machine (Architecture) -#define EM_NONE 0 // No machine -#define EM_M32 1 // AT&T WE 32100 -#define EM_SPARC 2 // Sparc -#define EM_386 3 // Intel 80386 -#define EM_68K 4 // Motorola m68k family -#define EM_88K 5 // Motorola m88k family -#define EM_486 6 // Intel 80486, Reserved for future use -#define EM_860 7 // Intel 80860 -#define EM_MIPS 8 // MIPS R3000 (officially, big-endian only) -#define EM_S370 9 // IBM System/370 -#define EM_MIPS_RS3_LE 10 // MIPS R3000 little-endian, Deprecated -#define EM_PARISC 15 // HPPA -#define EM_VPP550 17 // Fujitsu VPP500 -#define EM_SPARC32PLUS 18 // Sun "v8plus" -#define EM_960 19 // Intel 80960 -#define EM_PPC 20 // PowerPC -#define EM_PPC64 21 // 64-bit PowerPC -#define EM_S390 22 // IBM S/390 -#define EM_V800 36 // NEC V800 series -#define EM_FR20 37 // Fujitsu FR20 -#define EM_RH32 38 // TRW RH32 -#define EM_MCORE 39 // Motorola M*Core -#define EM_RCE 39 // Old name for MCore -#define EM_ARM 40 // ARM -#define EM_OLD_ALPHA 41 // Digital Alpha -#define EM_SH 42 // Renesas / SuperH SH -#define EM_SPARCV9 43 // SPARC v9 64-bit -#define EM_TRICORE 44 // Siemens Tricore embedded processor -#define EM_ARC 45 // ARC Cores -#define EM_H8_300 46 // Renesas H8/300 -#define EM_H8_300H 47 // Renesas H8/300H -#define EM_H8S 48 // Renesas H8S -#define EM_H8_500 49 // Renesas H8/500 -#define EM_IA_64 50 // Intel IA-64 Processor -#define EM_MIPS_X 51 // Stanford MIPS-X -#define EM_COLDFIRE 52 // Motorola Coldfire -#define EM_68HC12 53 // Motorola M68HC12 -#define EM_MMA 54 // Fujitsu Multimedia Accelerator -#define EM_PCP 55 // Siemens PCP -#define EM_NCPU 56 // Sony nCPU embedded RISC processor -#define EM_NDR1 57 // Denso NDR1 microprocesspr -#define EM_STARCORE 58 // Motorola Star*Core processor -#define EM_ME16 59 // Toyota ME16 processor -#define EM_ST100 60 // STMicroelectronics ST100 processor -#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor -#define EM_X86_64 62 // Advanced Micro Devices X86-64 processor - -// architecture class (EI_CLASS) -#define ELFCLASS32 1 -#define ELFCLASS64 2 -// endian (EI_DATA) -#define ELFDATA2LSB 1 /* little endian */ -#define ELFDATA2MSB 2 /* big endian */ - /*** section header ***/ @@ -131,45 +59,6 @@ struct Elf32_Shdr { Elf32_Word sh_entsize; }; -// special section indices -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -// section header type -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 - -#define SHT_GNU_verdef 0x6ffffffd /* version definition section */ -#define SHT_GNU_verneed 0x6ffffffe /* version needs section */ -#define SHT_GNU_versym 0x6fffffff /* version symbol table */ - -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -// section header flags -#define SHF_WRITE 1 -#define SHF_ALLOC 2 -#define SHF_EXECINSTR 4 - -#define SHF_MASKPROC 0xf0000000 - /*** program header ***/ @@ -189,27 +78,6 @@ struct Elf32_Phdr { #endif }; -// program header segment types -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_STACK 0x6474e551 - -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff - -// program header segment flags -#define PF_EXECUTE 0x1 -#define PF_WRITE 0x2 -#define PF_READ 0x4 -#define PF_PROTECTION_MASK (PF_EXECUTE | PF_WRITE | PF_READ) - -#define PF_MASKPROC 0xf0000000 - struct Elf32_Sym { Elf32_Word st_name; Elf32_Addr st_value; @@ -228,22 +96,6 @@ struct Elf32_Sym { #define ELF32_ST_TYPE(i) ((i) & 0xf) #define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xf)) -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_LOPROC 13 -#define STT_HIPROC 15 - -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 -#define STB_LOPROC 13 -#define STB_HIPROC 15 - -#define STN_UNDEF 0 - struct Elf32_Rel { Elf32_Addr r_offset; Elf32_Word r_info; @@ -276,58 +128,6 @@ struct Elf32_Dyn { } d_un; }; -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_BIND_NOW 24 /* no lazy binding */ -#define DT_INIT_ARRAY 25 /* init function array */ -#define DT_FINI_ARRAY 26 /* termination function array */ -#define DT_INIT_ARRAYSZ 27 /* init function array size */ -#define DT_FINI_ARRAYSZ 28 /* termination function array size */ -#define DT_RUNPATH 29 /* library search path (supersedes DT_RPATH) */ -#define DT_FLAGS 30 /* flags (see below) */ -#define DT_ENCODING 32 -#define DT_PREINIT_ARRAY 32 /* preinitialization array */ -#define DT_PREINIT_ARRAYSZ 33 /* preinitialization array size */ - -#define DT_VERSYM 0x6ffffff0 /* symbol version table */ -#define DT_VERDEF 0x6ffffffc /* version definition table */ -#define DT_VERDEFNUM 0x6ffffffd /* number of version definitions */ -#define DT_VERNEED 0x6ffffffe /* table with needed versions */ -#define DT_VERNEEDNUM 0x6fffffff /* number of needed versions */ - -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - - -/* DT_FLAGS values */ -#define DF_ORIGIN 0x01 -#define DF_SYMBOLIC 0x02 -#define DF_TEXTREL 0x04 -#define DF_BIND_NOW 0x08 -#define DF_STATIC_TLS 0x10 - /* version definition section */ @@ -342,30 +142,6 @@ struct Elf32_Verdef { Elf32_Word vd_next; /* byte offset to next verdef entry */ }; -/* values for vd_version (version revision) */ -#define VER_DEF_NONE 0 /* no version */ -#define VER_DEF_CURRENT 1 /* current version */ -#define VER_DEF_NUM 2 /* given version number */ - -/* values for vd_flags (version information flags) */ -#define VER_FLG_BASE 0x1 /* version definition of file itself */ -#define VER_FLG_WEAK 0x2 /* weak version identifier */ - -/* values for versym symbol index */ -#define VER_NDX_LOCAL 0 /* symbol is local */ -#define VER_NDX_GLOBAL 1 /* symbol is global/unversioned */ -#define VER_NDX_INITIAL 2 /* initial version -- that's the one given - to symbols when a library becomes - versioned; handled by the linker (and - runtime loader) similar to - VER_NDX_GLOBAL */ -#define VER_NDX_LORESERVE 0xff00 /* beginning of reserved entries */ -#define VER_NDX_ELIMINATE 0xff01 /* symbol is to be eliminated */ - -#define VER_NDX_FLAG_HIDDEN 0x8000 /* flag: version is hidden */ -#define VER_NDX_MASK 0x7fff /* mask to get the actual version index */ -#define VER_NDX(x) ((x) & VER_NDX_MASK) - /* auxiliary version information */ @@ -387,11 +163,6 @@ struct Elf32_Verneed { Elf32_Word vn_next; /* byte offset to next verneed entry */ }; -/* values for vn_version (version revision) */ -#define VER_NEED_NONE 0 /* no version */ -#define VER_NEED_CURRENT 1 /* current version */ -#define VER_NEED_NUM 2 /* given version number */ - /* auxiliary needed version information */ @@ -404,9 +175,6 @@ struct Elf32_Vernaux { Elf32_Word vna_next; /* byte offset to next vernaux entry */ }; -/* values for vna_flags */ -#define VER_FLG_WEAK 0x2 /* weak version identifier */ - /*** inline functions ***/ diff --git a/headers/private/system/elf64.h b/headers/private/system/elf64.h new file mode 100644 index 0000000000..dc354060a1 --- /dev/null +++ b/headers/private/system/elf64.h @@ -0,0 +1,239 @@ +/* + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + * + * Copyright 2002-2011, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + */ +#ifndef _ELF64_H +#define _ELF64_H + + +#include + + +typedef uint64 Elf64_Addr; +typedef uint64 Elf64_Off; +typedef uint16 Elf64_Half; +typedef uint32 Elf64_Word; +typedef int32 Elf64_Sword; +typedef uint64 Elf64_Xword; +typedef int64 Elf64_Sxword; + +typedef Elf64_Half Elf64_Versym; + +/*** ELF header ***/ + +struct Elf64_Ehdr { + uint8 e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; + +#ifdef __cplusplus + bool IsHostEndian() const; +#endif +}; + + +/*** section header ***/ + +struct Elf64_Shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + + +/*** program header ***/ + +struct Elf64_Phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* offset from the beginning of the file of the segment */ + Elf64_Addr p_vaddr; /* virtual address for the segment in memory */ + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; /* the size of the segment in the file */ + Elf64_Xword p_memsz; /* the size of the segment in memory */ + Elf64_Xword p_align; + +#ifdef __cplusplus + bool IsReadWrite() const; + bool IsExecutable() const; +#endif +}; + +struct Elf64_Sym { + Elf64_Word st_name; + uint8 st_info; + uint8 st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; + +#ifdef __cplusplus + uint8 Bind() const; + uint8 Type() const; +#endif +}; + +#define ELF64_ST_BIND(i) ((i) >> 4) +#define ELF64_ST_TYPE(i) ((i) & 0xf) +#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t) & 0xf)) + +struct Elf64_Rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; + +#ifdef __cplusplus + uint8 SymbolIndex() const; + uint8 Type() const; +#endif +}; + +#ifdef __cplusplus +struct Elf64_Rela : public Elf64_Rel { +#else +struct Elf64_Rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; +#endif + Elf64_Sxword r_addend; +}; + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffffL) +#define ELF64_R_INFO(s, t) ((((Elf64_Xword)(s)) << 32) + ((t) & 0xffffffffL)) + +struct Elf64_Dyn { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +}; + + +/* version definition section */ + +struct Elf64_Verdef { + Elf64_Half vd_version; /* version revision */ + Elf64_Half vd_flags; /* version information flags */ + Elf64_Half vd_ndx; /* version index as specified in the + symbol version table */ + Elf64_Half vd_cnt; /* number of associated verdaux entries */ + Elf64_Word vd_hash; /* version name hash value */ + Elf64_Word vd_aux; /* byte offset to verdaux array */ + Elf64_Word vd_next; /* byte offset to next verdef entry */ +}; + + +/* auxiliary version information */ + +struct Elf64_Verdaux { + Elf64_Word vda_name; /* string table offset to version or dependency + name */ + Elf64_Word vda_next; /* byte offset to next verdaux entry */ +}; + + +/* version dependency section */ + +struct Elf64_Verneed { + Elf64_Half vn_version; /* version of structure */ + Elf64_Half vn_cnt; /* number of associated vernaux entries */ + Elf64_Word vn_file; /* byte offset to file name for this + dependency */ + Elf64_Word vn_aux; /* byte offset to vernaux array */ + Elf64_Word vn_next; /* byte offset to next verneed entry */ +}; + + +/* auxiliary needed version information */ + +struct Elf64_Vernaux { + Elf64_Word vna_hash; /* dependency name hash value */ + Elf64_Half vna_flags; /* dependency specific information flags */ + Elf64_Half vna_other; /* version index as specified in the symbol + version table */ + Elf64_Word vna_name; /* string table offset to dependency name */ + Elf64_Word vna_next; /* byte offset to next vernaux entry */ +}; + + +/*** inline functions ***/ + +#ifdef __cplusplus + +inline bool +Elf64_Ehdr::IsHostEndian() const +{ +#if B_HOST_IS_LENDIAN + return e_ident[EI_DATA] == ELFDATA2LSB; +#elif B_HOST_IS_BENDIAN + return e_ident[EI_DATA] == ELFDATA2MSB; +#endif +} + + +inline bool +Elf64_Phdr::IsReadWrite() const +{ + return !(~p_flags & (PF_READ | PF_WRITE)); +} + + +inline bool +Elf64_Phdr::IsExecutable() const +{ + return (p_flags & PF_EXECUTE) != 0; +} + + +inline uint8 +Elf64_Sym::Bind() const +{ + return ELF64_ST_BIND(st_info); +} + + +inline uint8 +Elf64_Sym::Type() const +{ + return ELF64_ST_TYPE(st_info); +} + + +inline uint8 +Elf64_Rel::SymbolIndex() const +{ + return ELF64_R_SYM(r_info); +} + + +inline uint8 +Elf64_Rel::Type() const +{ + return ELF64_R_TYPE(r_info); +} + +#endif /* __cplusplus */ + +#endif /* _ELF64_H_ */ diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h new file mode 100644 index 0000000000..6a85bf2012 --- /dev/null +++ b/headers/private/system/elf_common.h @@ -0,0 +1,274 @@ +/* + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + * + * Copyright 2002-2011, Haiku Inc. All Rights Reserved. + * Distributed under the terms of the MIT license. + */ +#ifndef _ELF_COMMON_H +#define _ELF_COMMON_H + + +#include +#include + +#include + + +typedef uint32 Elf32_Addr; +typedef uint16 Elf32_Half; +typedef uint32 Elf32_Off; +typedef int32 Elf32_Sword; +typedef uint32 Elf32_Word; + +typedef Elf32_Half Elf32_Versym; + +/*** ELF header ***/ + +#define EI_NIDENT 16 + +#define ELF_MAGIC "\x7f""ELF" + +// e_ident[] indices +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_PAD 7 + +// e_machine (Architecture) +#define EM_NONE 0 // No machine +#define EM_M32 1 // AT&T WE 32100 +#define EM_SPARC 2 // Sparc +#define EM_386 3 // Intel 80386 +#define EM_68K 4 // Motorola m68k family +#define EM_88K 5 // Motorola m88k family +#define EM_486 6 // Intel 80486, Reserved for future use +#define EM_860 7 // Intel 80860 +#define EM_MIPS 8 // MIPS R3000 (officially, big-endian only) +#define EM_S370 9 // IBM System/370 +#define EM_MIPS_RS3_LE 10 // MIPS R3000 little-endian, Deprecated +#define EM_PARISC 15 // HPPA +#define EM_VPP550 17 // Fujitsu VPP500 +#define EM_SPARC32PLUS 18 // Sun "v8plus" +#define EM_960 19 // Intel 80960 +#define EM_PPC 20 // PowerPC +#define EM_PPC64 21 // 64-bit PowerPC +#define EM_S390 22 // IBM S/390 +#define EM_V800 36 // NEC V800 series +#define EM_FR20 37 // Fujitsu FR20 +#define EM_RH32 38 // TRW RH32 +#define EM_MCORE 39 // Motorola M*Core +#define EM_RCE 39 // Old name for MCore +#define EM_ARM 40 // ARM +#define EM_OLD_ALPHA 41 // Digital Alpha +#define EM_SH 42 // Renesas / SuperH SH +#define EM_SPARCV9 43 // SPARC v9 64-bit +#define EM_TRICORE 44 // Siemens Tricore embedded processor +#define EM_ARC 45 // ARC Cores +#define EM_H8_300 46 // Renesas H8/300 +#define EM_H8_300H 47 // Renesas H8/300H +#define EM_H8S 48 // Renesas H8S +#define EM_H8_500 49 // Renesas H8/500 +#define EM_IA_64 50 // Intel IA-64 Processor +#define EM_MIPS_X 51 // Stanford MIPS-X +#define EM_COLDFIRE 52 // Motorola Coldfire +#define EM_68HC12 53 // Motorola M68HC12 +#define EM_MMA 54 // Fujitsu Multimedia Accelerator +#define EM_PCP 55 // Siemens PCP +#define EM_NCPU 56 // Sony nCPU embedded RISC processor +#define EM_NDR1 57 // Denso NDR1 microprocesspr +#define EM_STARCORE 58 // Motorola Star*Core processor +#define EM_ME16 59 // Toyota ME16 processor +#define EM_ST100 60 // STMicroelectronics ST100 processor +#define EM_TINYJ 61 // Advanced Logic Corp. TinyJ embedded processor +#define EM_X86_64 62 // Advanced Micro Devices X86-64 processor + +// architecture class (EI_CLASS) +#define ELFCLASS32 1 +#define ELFCLASS64 2 +// endian (EI_DATA) +#define ELFDATA2LSB 1 /* little endian */ +#define ELFDATA2MSB 2 /* big endian */ + + +/*** section header ***/ + +// special section indices +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +// section header type +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 + +#define SHT_GNU_verdef 0x6ffffffd /* version definition section */ +#define SHT_GNU_verneed 0x6ffffffe /* version needs section */ +#define SHT_GNU_versym 0x6fffffff /* version symbol table */ + +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +// section header flags +#define SHF_WRITE 1 +#define SHF_ALLOC 2 +#define SHF_EXECINSTR 4 + +#define SHF_MASKPROC 0xf0000000 + + +/*** program header ***/ + +// program header segment types +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_STACK 0x6474e551 + +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +// program header segment flags +#define PF_EXECUTE 0x1 +#define PF_WRITE 0x2 +#define PF_READ 0x4 +#define PF_PROTECTION_MASK (PF_EXECUTE | PF_WRITE | PF_READ) + +#define PF_MASKPROC 0xf0000000 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STN_UNDEF 0 + + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_BIND_NOW 24 /* no lazy binding */ +#define DT_INIT_ARRAY 25 /* init function array */ +#define DT_FINI_ARRAY 26 /* termination function array */ +#define DT_INIT_ARRAYSZ 27 /* init function array size */ +#define DT_FINI_ARRAYSZ 28 /* termination function array size */ +#define DT_RUNPATH 29 /* library search path (supersedes DT_RPATH) */ +#define DT_FLAGS 30 /* flags (see below) */ +#define DT_ENCODING 32 +#define DT_PREINIT_ARRAY 32 /* preinitialization array */ +#define DT_PREINIT_ARRAYSZ 33 /* preinitialization array size */ + +#define DT_VERSYM 0x6ffffff0 /* symbol version table */ +#define DT_VERDEF 0x6ffffffc /* version definition table */ +#define DT_VERDEFNUM 0x6ffffffd /* number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* table with needed versions */ +#define DT_VERNEEDNUM 0x6fffffff /* number of needed versions */ + +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + + +/* DT_FLAGS values */ +#define DF_ORIGIN 0x01 +#define DF_SYMBOLIC 0x02 +#define DF_TEXTREL 0x04 +#define DF_BIND_NOW 0x08 +#define DF_STATIC_TLS 0x10 + + +/* version definition section */ + +/* values for vd_version (version revision) */ +#define VER_DEF_NONE 0 /* no version */ +#define VER_DEF_CURRENT 1 /* current version */ +#define VER_DEF_NUM 2 /* given version number */ + +/* values for vd_flags (version information flags) */ +#define VER_FLG_BASE 0x1 /* version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* weak version identifier */ + +/* values for versym symbol index */ +#define VER_NDX_LOCAL 0 /* symbol is local */ +#define VER_NDX_GLOBAL 1 /* symbol is global/unversioned */ +#define VER_NDX_INITIAL 2 /* initial version -- that's the one given + to symbols when a library becomes + versioned; handled by the linker (and + runtime loader) similar to + VER_NDX_GLOBAL */ +#define VER_NDX_LORESERVE 0xff00 /* beginning of reserved entries */ +#define VER_NDX_ELIMINATE 0xff01 /* symbol is to be eliminated */ + +#define VER_NDX_FLAG_HIDDEN 0x8000 /* flag: version is hidden */ +#define VER_NDX_MASK 0x7fff /* mask to get the actual version index */ +#define VER_NDX(x) ((x) & VER_NDX_MASK) + + +/* version dependency section */ + +/* values for vn_version (version revision) */ +#define VER_NEED_NONE 0 /* no version */ +#define VER_NEED_CURRENT 1 /* current version */ +#define VER_NEED_NUM 2 /* given version number */ + + +/* auxiliary needed version information */ + +/* values for vna_flags */ +#define VER_FLG_WEAK 0x2 /* weak version identifier */ + + +#endif /* _ELF_COMMON_H_ */ From 62d36f98331067e472188f6c020c2ccd808f48cf Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 16:56:56 +0100 Subject: [PATCH 028/273] Removed the addr_t conversion operators from FixedWidthPointer which makes comparison against NULL work properly. --- .../private/kernel/util/FixedWidthPointer.h | 24 +++++++++++-------- src/system/boot/platform/bios_ia32/debug.cpp | 2 +- src/system/boot/platform/bios_ia32/smp.cpp | 6 ++--- src/system/boot/platform/bios_ia32/video.cpp | 2 +- .../boot/platform/generic/video_splash.cpp | 4 ++-- .../boot/platform/openfirmware/video.cpp | 2 +- src/system/boot/platform/u-boot/serial.cpp | 2 +- src/system/kernel/arch/x86/apic.cpp | 2 +- src/system/kernel/arch/x86/ioapic.cpp | 2 +- .../kernel/arch/x86/timers/x86_hpet.cpp | 2 +- src/system/kernel/debug/debug.cpp | 6 ++--- .../kernel/debug/frame_buffer_console.cpp | 2 +- 12 files changed, 30 insertions(+), 26 deletions(-) diff --git a/headers/private/kernel/util/FixedWidthPointer.h b/headers/private/kernel/util/FixedWidthPointer.h index b6e9662e72..56d88afaef 100644 --- a/headers/private/kernel/util/FixedWidthPointer.h +++ b/headers/private/kernel/util/FixedWidthPointer.h @@ -25,11 +25,6 @@ public: return (Type *)(addr_t)fValue; } - operator addr_t() const - { - return (addr_t)fValue; - } - Type& operator*() const { return *(Type *)*this; @@ -90,11 +85,6 @@ public: return (OtherType*)(addr_t)fValue; } - operator addr_t() const - { - return (addr_t)fValue; - } - FixedWidthPointer& operator=(const FixedWidthPointer& p) { fValue = p.fValue; @@ -121,5 +111,19 @@ private: uint64 fValue; } _PACKED; +template +inline bool +operator==(const FixedWidthPointer& a, void* b) +{ + return a.Get() == (addr_t)b; +} + +template +inline bool +operator!=(const FixedWidthPointer& a, void* b) +{ + return a.Get() != (addr_t)b; +} + #endif /* KERNEL_UTIL_FIXED_WIDTH_POINTER_H */ diff --git a/src/system/boot/platform/bios_ia32/debug.cpp b/src/system/boot/platform/bios_ia32/debug.cpp index deb389dce5..73d2906415 100644 --- a/src/system/boot/platform/bios_ia32/debug.cpp +++ b/src/system/boot/platform/bios_ia32/debug.cpp @@ -162,7 +162,7 @@ debug_cleanup(void) if (!gKernelArgs.keep_debug_output_buffer) { gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); - if (gKernelArgs.debug_output) { + if (gKernelArgs.debug_output != NULL) { memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); gKernelArgs.debug_size = sBufferPosition; } diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index f31af15f2a..2944655a99 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -60,21 +60,21 @@ static int smp_get_current_cpu(void); static uint32 apic_read(uint32 offset) { - return *(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic + offset); + return *(volatile uint32 *)((addr_t)(void *)gKernelArgs.arch_args.apic + offset); } static void apic_write(uint32 offset, uint32 data) { - *(volatile uint32 *)((addr_t)gKernelArgs.arch_args.apic + offset) = data; + *(volatile uint32 *)((addr_t)(void *)gKernelArgs.arch_args.apic + offset) = data; } static int smp_get_current_cpu(void) { - if (!gKernelArgs.arch_args.apic) + if (gKernelArgs.arch_args.apic == NULL) return 0; uint8 apicID = apic_read(APIC_ID) >> 24; diff --git a/src/system/boot/platform/bios_ia32/video.cpp b/src/system/boot/platform/bios_ia32/video.cpp index be634ff29a..fa9b1fba8c 100644 --- a/src/system/boot/platform/bios_ia32/video.cpp +++ b/src/system/boot/platform/bios_ia32/video.cpp @@ -957,7 +957,7 @@ platform_init_video(void) } gKernelArgs.edid_info = kernel_args_malloc(sizeof(edid1_info)); - if (gKernelArgs.edid_info) + if (gKernelArgs.edid_info != NULL) memcpy(gKernelArgs.edid_info, &info, sizeof(edid1_info)); } diff --git a/src/system/boot/platform/generic/video_splash.cpp b/src/system/boot/platform/generic/video_splash.cpp index ceebb2eab1..5d1c41166a 100644 --- a/src/system/boot/platform/generic/video_splash.cpp +++ b/src/system/boot/platform/generic/video_splash.cpp @@ -146,7 +146,7 @@ video_display_splash(addr_t frameBuffer) // pointer into the lower half of the icons image data gKernelArgs.boot_splash = (uint8*)kernel_args_malloc(uncompressedSize); - if (!gKernelArgs.boot_splash) + if (gKernelArgs.boot_splash == NULL) return B_NO_MEMORY; uncompress(kSplashIcons8BitCompressedImage, sizeof(kSplashIcons8BitCompressedImage), @@ -159,7 +159,7 @@ video_display_splash(addr_t frameBuffer) // pointer into the lower half of the icons image data gKernelArgs.boot_splash = (uint8*)kernel_args_malloc(uncompressedSize); - if (!gKernelArgs.boot_splash) + if (gKernelArgs.boot_splash == NULL) return B_NO_MEMORY; uncompress(kSplashIcons24BitCompressedImage, sizeof(kSplashIcons24BitCompressedImage), diff --git a/src/system/boot/platform/openfirmware/video.cpp b/src/system/boot/platform/openfirmware/video.cpp index d996cd9035..639723d09b 100644 --- a/src/system/boot/platform/openfirmware/video.cpp +++ b/src/system/boot/platform/openfirmware/video.cpp @@ -126,7 +126,7 @@ platform_init_video(void) edid_dump(&info); #endif gKernelArgs.edid_info = kernel_args_malloc(sizeof(edid1_info)); - if (gKernelArgs.edid_info) + if (gKernelArgs.edid_info != NULL) memcpy(gKernelArgs.edid_info, &info, sizeof(edid1_info)); } diff --git a/src/system/boot/platform/u-boot/serial.cpp b/src/system/boot/platform/u-boot/serial.cpp index 4ba65ef26a..12c6357d26 100644 --- a/src/system/boot/platform/u-boot/serial.cpp +++ b/src/system/boot/platform/u-boot/serial.cpp @@ -83,7 +83,7 @@ serial_cleanup(void) return; gKernelArgs.debug_output = kernel_args_malloc(sBufferPosition); - if (gKernelArgs.debug_output) { + if (gKernelArgs.debug_output != NULL) { memcpy(gKernelArgs.debug_output, sBuffer, sBufferPosition); gKernelArgs.debug_size = sBufferPosition; } diff --git a/src/system/kernel/arch/x86/apic.cpp b/src/system/kernel/arch/x86/apic.cpp index 12492003ae..2c83935402 100644 --- a/src/system/kernel/arch/x86/apic.cpp +++ b/src/system/kernel/arch/x86/apic.cpp @@ -68,7 +68,7 @@ apic_disable_local_ints() status_t apic_init(kernel_args *args) { - if (!args->arch_args.apic) + if (args->arch_args.apic == NULL) return B_NO_INIT; sLocalAPIC = args->arch_args.apic; diff --git a/src/system/kernel/arch/x86/ioapic.cpp b/src/system/kernel/arch/x86/ioapic.cpp index fa23b17571..6d40b1645b 100644 --- a/src/system/kernel/arch/x86/ioapic.cpp +++ b/src/system/kernel/arch/x86/ioapic.cpp @@ -650,7 +650,7 @@ ioapic_init(kernel_args* args) &ioapic_end_of_interrupt }; - if (!args->arch_args.apic) + if (args->arch_args.apic == NULL) return; if (args->arch_args.ioapic_phys == 0) { diff --git a/src/system/kernel/arch/x86/timers/x86_hpet.cpp b/src/system/kernel/arch/x86/timers/x86_hpet.cpp index e75a8795e0..d5dfa48693 100644 --- a/src/system/kernel/arch/x86/timers/x86_hpet.cpp +++ b/src/system/kernel/arch/x86/timers/x86_hpet.cpp @@ -217,7 +217,7 @@ hpet_init(struct kernel_args *args) /* hpet_acpi_probe() through a similar "scan spots" table to that of smp.cpp. Seems to be the most elegant solution right now. */ - if (!args->arch_args.hpet) + if (args->arch_args.hpet == NULL) return B_ERROR; if (sHPETRegs == NULL) { diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 0a4d759dd1..791c827448 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1384,7 +1384,7 @@ syslog_init_post_vm(struct kernel_args* args) } } else { // create an area for the debug syslog buffer - void* base = (void*)ROUNDDOWN((addr_t)args->debug_output, B_PAGE_SIZE); + void* base = (void*)ROUNDDOWN((addr_t)(void *)args->debug_output, B_PAGE_SIZE); size_t size = ROUNDUP(args->debug_size, B_PAGE_SIZE); area_id area = create_area("syslog debug", &base, B_EXACT_ADDRESS, size, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); @@ -1401,7 +1401,7 @@ syslog_init_post_vm(struct kernel_args* args) sSyslogMessage->ident[0] = '\0'; //strcpy(sSyslogMessage->ident, "KERNEL"); - if (args->debug_output) + if (args->debug_output != NULL) syslog_write((const char*)args->debug_output, args->debug_size, false); char revisionBuffer[64]; @@ -1431,7 +1431,7 @@ err1: static status_t syslog_init(struct kernel_args* args) { - if (!args->keep_debug_output_buffer || !args->debug_output) + if (!args->keep_debug_output_buffer || args->debug_output == NULL) return B_OK; sSyslogBuffer = create_ring_buffer_etc(args->debug_output, args->debug_size, diff --git a/src/system/kernel/debug/frame_buffer_console.cpp b/src/system/kernel/debug/frame_buffer_console.cpp index 205f50d9d5..5a1f67d865 100644 --- a/src/system/kernel/debug/frame_buffer_console.cpp +++ b/src/system/kernel/debug/frame_buffer_console.cpp @@ -442,7 +442,7 @@ frame_buffer_console_init(kernel_args* args) add_boot_item(VESA_MODES_BOOT_INFO, sVesaModes, args->vesa_modes_size); } - if (args->edid_info) { + if (args->edid_info != NULL) { edid1_info* info = (edid1_info*)malloc(sizeof(edid1_info)); if (info != NULL) { memcpy(info, args->edid_info, sizeof(edid1_info)); From f1244978152350f9cc010e766d09c2e9ad34dfce Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 19:24:51 +0100 Subject: [PATCH 029/273] Added an ELF64 version of preloaded_image. * There is now 2 structures, preloaded_elf32_image and preloaded_elf64_image, which both inherit from preloaded_image. * For now I've just hardcoded in use of preloaded_elf32_image, but the bootloader ELF code will shortly be converted to use templates which use the appropriate structure. The kernel will be changed later when I add ELF64 support to it. * All kernel_args data is now compatible between 32-bit and 64-bit kernels. --- headers/private/kernel/boot/arch.h | 4 +- headers/private/kernel/boot/elf.h | 70 ++++++++++++++----- headers/private/kernel/boot/kernel_args.h | 2 +- headers/private/kernel/elf_priv.h | 1 + src/system/boot/loader/Jamfile | 2 + src/system/boot/loader/elf.cpp | 58 +++++++++------ src/system/boot/loader/elf.h | 4 +- src/system/boot/loader/loader.cpp | 9 ++- src/system/boot/platform/amiga_m68k/start.cpp | 8 ++- src/system/boot/platform/atari_m68k/start.cpp | 8 ++- src/system/boot/platform/bios_ia32/smp.cpp | 5 +- src/system/boot/platform/bios_ia32/start.cpp | 8 ++- src/system/boot/platform/cfe/start.cpp | 5 +- .../boot/platform/openfirmware/start.cpp | 5 +- src/system/boot/platform/u-boot/start.cpp | 8 ++- src/system/kernel/arch/arm/arch_elf.cpp | 4 +- src/system/kernel/arch/m68k/arch_elf.cpp | 4 +- src/system/kernel/arch/mipsel/arch_elf.cpp | 4 +- src/system/kernel/arch/ppc/arch_elf.cpp | 4 +- src/system/kernel/arch/x86/arch_elf.cpp | 4 +- .../kernel/device_manager/legacy_drivers.cpp | 2 +- src/system/kernel/elf.cpp | 21 ++++-- src/system/kernel/module.cpp | 2 +- src/system/kernel/vm/vm.cpp | 13 +++- 24 files changed, 171 insertions(+), 84 deletions(-) diff --git a/headers/private/kernel/boot/arch.h b/headers/private/kernel/boot/arch.h index 0eabf2c7e4..8642efe57e 100644 --- a/headers/private/kernel/boot/arch.h +++ b/headers/private/kernel/boot/arch.h @@ -15,9 +15,9 @@ extern "C" { /* ELF support */ -extern status_t boot_arch_elf_relocate_rel(struct preloaded_image *image, +extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image *image, struct Elf32_Rel *rel, int rel_len); -extern status_t boot_arch_elf_relocate_rela(struct preloaded_image *image, +extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image *image, struct Elf32_Rela *rel, int rel_len); diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 3cc17049d4..1ef93c2b16 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -11,27 +11,29 @@ #include #include +typedef struct elf32_region { + area_id id; + uint32 start; + uint32 size; + int32 delta; +} _PACKED elf32_region; + +typedef struct elf64_region { + area_id id; + uint64 start; + uint64 size; + int64 delta; +} _PACKED elf64_region; struct preloaded_image { FixedWidthPointer next; - char *name; - elf_region text_region; - elf_region data_region; + FixedWidthPointer name; + uint8 elf_class; addr_range dynamic_section; - struct Elf32_Ehdr elf_header; - struct Elf32_Sym *syms; - struct Elf32_Rel *rel; - int rel_len; - struct Elf32_Rela *rela; - int rela_len; - struct Elf32_Rel *pltrel; - int pltrel_len; - int pltrel_type; - - struct Elf32_Sym *debug_symbols; - const char *debug_string_table; - uint32 num_debug_symbols, debug_string_table_size; + FixedWidthPointer debug_string_table; + uint32 num_debug_symbols; + uint32 debug_string_table_size; ino_t inode; image_id id; @@ -40,11 +42,45 @@ struct preloaded_image { // set by the module initialization code } _PACKED; +struct preloaded_elf32_image : public preloaded_image { + Elf32_Ehdr elf_header; + elf32_region text_region; + elf32_region data_region; + + FixedWidthPointer syms; + FixedWidthPointer rel; + int32 rel_len; + FixedWidthPointer rela; + int32 rela_len; + FixedWidthPointer pltrel; + int32 pltrel_len; + int32 pltrel_type; + + FixedWidthPointer debug_symbols; +} _PACKED; + +struct preloaded_elf64_image : public preloaded_image { + Elf64_Ehdr elf_header; + elf64_region text_region; + elf64_region data_region; + + FixedWidthPointer syms; + FixedWidthPointer rel; + int64 rel_len; + FixedWidthPointer rela; + int64 rela_len; + FixedWidthPointer pltrel; + int64 pltrel_len; + int64 pltrel_type; + + FixedWidthPointer debug_symbols; +} _PACKED; + #ifdef __cplusplus extern "C" { #endif -extern status_t boot_elf_resolve_symbol(struct preloaded_image *image, +extern status_t boot_elf_resolve_symbol(struct preloaded_elf32_image *image, struct Elf32_Sym *symbol, addr_t *symbolAddress); #ifdef __cplusplus diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index b2e7ee93fb..de7fb735e6 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -44,7 +44,7 @@ typedef struct kernel_args { uint32 kernel_args_size; uint32 version; - struct preloaded_image kernel_image; + FixedWidthPointer kernel_image; FixedWidthPointer preloaded_images; uint32 num_physical_memory_ranges; diff --git a/headers/private/kernel/elf_priv.h b/headers/private/kernel/elf_priv.h index 1594d1c639..8169574606 100644 --- a/headers/private/kernel/elf_priv.h +++ b/headers/private/kernel/elf_priv.h @@ -10,6 +10,7 @@ #include +#include #include diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index 00135e2711..f325c3279f 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -39,6 +39,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86_64\\\" + BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI @@ -49,6 +50,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86\\\" + BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 1e56c90453..841966b979 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -1,5 +1,6 @@ /* * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. */ @@ -61,7 +62,7 @@ verify_elf_header(struct Elf32_Ehdr &header) static status_t -elf_parse_dynamic_section(struct preloaded_image *image) +elf_parse_dynamic_section(preloaded_elf32_image *image) { image->syms = 0; image->rel = 0; @@ -124,7 +125,7 @@ elf_parse_dynamic_section(struct preloaded_image *image) static status_t -load_elf_symbol_table(int fd, preloaded_image *image) +load_elf_symbol_table(int fd, preloaded_elf32_image *image) { struct Elf32_Ehdr &elfHeader = image->elf_header; Elf32_Sym *symbolTable = NULL; @@ -226,28 +227,40 @@ error1: status_t -elf_load_image(int fd, preloaded_image *image) +elf_load_image(int fd, preloaded_image **_image) { size_t totalSize; status_t status; - TRACE(("elf_load_image(fd = %d, image = %p)\n", fd, image)); + TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); + + preloaded_elf32_image *image = (preloaded_elf32_image *)kernel_args_malloc( + sizeof(preloaded_elf32_image)); + if (image == NULL) + return B_NO_MEMORY; struct Elf32_Ehdr &elfHeader = image->elf_header; ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(Elf32_Ehdr)); - if (length < (ssize_t)sizeof(Elf32_Ehdr)) + if (length < (ssize_t)sizeof(Elf32_Ehdr)) { + kernel_args_free(image); return B_BAD_TYPE; + } status = verify_elf_header(elfHeader); - if (status < B_OK) + if (status < B_OK) { + kernel_args_free(image); return status; + } + + image->elf_class = elfHeader.e_ident[EI_CLASS]; ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize; Elf32_Phdr *programHeaders = (struct Elf32_Phdr *)malloc(size); if (programHeaders == NULL) { dprintf("error allocating space for program headers\n"); - return B_NO_MEMORY; + status = B_NO_MEMORY; + goto error1; } length = read_pos(fd, elfHeader.e_phoff, programHeaders, size); @@ -281,7 +294,7 @@ elf_load_image(int fd, preloaded_image *image) continue; } - elf_region *region; + elf32_region *region; if (header.IsReadWrite()) { if (image->data_region.size != 0) { dprintf("elf: rw already handled!\n"); @@ -302,7 +315,7 @@ elf_load_image(int fd, preloaded_image *image) B_PAGE_SIZE); region->delta = -region->start; - TRACE(("segment %d: start = %p, size = %lu, delta = %lx\n", i, + TRACE(("segment %ld: start = 0x%lx, size = %lu, delta = %lx\n", i, region->start, region->size, region->delta)); } @@ -314,8 +327,8 @@ elf_load_image(int fd, preloaded_image *image) } // get the segment order - elf_region *firstRegion; - elf_region *secondRegion; + elf32_region *firstRegion; + elf32_region *secondRegion; if (image->text_region.start < image->data_region.start) { firstRegion = &image->text_region; secondRegion = &image->data_region; @@ -356,7 +369,7 @@ elf_load_image(int fd, preloaded_image *image) if (header.p_type != PT_LOAD) continue; - elf_region *region; + elf32_region *region; if (header.IsReadWrite()) region = &image->data_region; else if (header.IsExecutable()) @@ -397,6 +410,7 @@ elf_load_image(int fd, preloaded_image *image) free(programHeaders); + *_image = image; return B_OK; error2: @@ -404,6 +418,7 @@ error2: platform_free_region((void *)image->text_region.start, totalSize); error1: free(programHeaders); + kernel_args_free(image); return status; } @@ -437,13 +452,7 @@ elf_load_image(Directory *directory, const char *path) // we still need to load it, so do it - image = (preloaded_image *)kernel_args_malloc(sizeof(preloaded_image)); - if (image == NULL) { - close(fd); - return B_NO_MEMORY; - } - - status_t status = elf_load_image(fd, image); + status_t status = elf_load_image(fd, &image); if (status == B_OK) { image->name = kernel_args_strdup(path); image->inode = stat.st_ino; @@ -460,8 +469,10 @@ elf_load_image(Directory *directory, const char *path) status_t -elf_relocate_image(struct preloaded_image *image) +elf_relocate_image(preloaded_image *_image) { + preloaded_elf32_image *image = static_cast(_image); + status_t status = elf_parse_dynamic_section(image); if (status != B_OK) return status; @@ -480,12 +491,13 @@ elf_relocate_image(struct preloaded_image *image) TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel))); + struct Elf32_Rel *pltrel = image->pltrel; if (image->pltrel_type == DT_REL) { - status = boot_arch_elf_relocate_rel(image, image->pltrel, + status = boot_arch_elf_relocate_rel(image, pltrel, image->pltrel_len); } else { status = boot_arch_elf_relocate_rela(image, - (struct Elf32_Rela *)image->pltrel, image->pltrel_len); + (struct Elf32_Rela *)pltrel, image->pltrel_len); } if (status < B_OK) return status; @@ -505,7 +517,7 @@ elf_relocate_image(struct preloaded_image *image) status_t -boot_elf_resolve_symbol(struct preloaded_image *image, +boot_elf_resolve_symbol(struct preloaded_elf32_image *image, struct Elf32_Sym *symbol, addr_t *symbolAddress) { switch (symbol->st_shndx) { diff --git a/src/system/boot/loader/elf.h b/src/system/boot/loader/elf.h index 8a899b6aff..9f5358a71f 100644 --- a/src/system/boot/loader/elf.h +++ b/src/system/boot/loader/elf.h @@ -12,8 +12,8 @@ extern void elf_init(); extern status_t elf_load_image(Directory *directory, const char *path); -extern status_t elf_load_image(int fd, preloaded_image *image); +extern status_t elf_load_image(int fd, preloaded_image **_image); -extern status_t elf_relocate_image(struct preloaded_image *image); +extern status_t elf_relocate_image(preloaded_image *image); #endif /* LOADER_ELF_H */ diff --git a/src/system/boot/loader/loader.cpp b/src/system/boot/loader/loader.cpp index 074bef5b3b..2edd7f2a68 100644 --- a/src/system/boot/loader/loader.cpp +++ b/src/system/boot/loader/loader.cpp @@ -93,7 +93,8 @@ load_kernel(stage2_args *args, Directory *volume) dprintf("load kernel %s...\n", name); elf_init(); - status_t status = elf_load_image(fd, &gKernelArgs.kernel_image); + preloaded_image *image; + status_t status = elf_load_image(fd, &image); close(fd); @@ -102,13 +103,15 @@ load_kernel(stage2_args *args, Directory *volume) return status; } - status = elf_relocate_image(&gKernelArgs.kernel_image); + gKernelArgs.kernel_image = image; + + status = elf_relocate_image(gKernelArgs.kernel_image); if (status < B_OK) { dprintf("relocating kernel failed: %lx!\n", status); return status; } - gKernelArgs.kernel_image.name = kernel_args_strdup(name); + gKernelArgs.kernel_image->name = kernel_args_strdup(name); return B_OK; } diff --git a/src/system/boot/platform/amiga_m68k/start.cpp b/src/system/boot/platform/amiga_m68k/start.cpp index 4cc21558e8..2356f85fb4 100644 --- a/src/system/boot/platform/amiga_m68k/start.cpp +++ b/src/system/boot/platform/amiga_m68k/start.cpp @@ -74,6 +74,9 @@ platform_start_kernel(void) addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; + preloaded_elf32_image *image = static_cast( + (void *)gKernelArgs.kernel_image); + //smp_init_other_cpus(); //serial_cleanup(); mmu_init_for_kernel(); @@ -81,8 +84,7 @@ platform_start_kernel(void) #warning M68K: stop ints - dprintf("kernel entry at %lx\n", - gKernelArgs.kernel_image.elf_header.e_entry); + dprintf("kernel entry at %lx\n", image->elf_header.e_entry); asm volatile ( "move.l %0,%%sp; " // move stack out of way @@ -97,7 +99,7 @@ platform_start_kernel(void) "move.l #0x0,-(%%sp);" // dummy retval for call to main "move.l %1,-(%%sp); " // this is the start address "rts; " // jump. - : : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry)); + : : "g" (args), "g" (image->elf_header.e_entry)); // Huston, we have a problem! diff --git a/src/system/boot/platform/atari_m68k/start.cpp b/src/system/boot/platform/atari_m68k/start.cpp index a7fd43ffbb..e03ee4165c 100644 --- a/src/system/boot/platform/atari_m68k/start.cpp +++ b/src/system/boot/platform/atari_m68k/start.cpp @@ -74,6 +74,9 @@ platform_start_kernel(void) addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; + preloaded_elf32_image *image = static_cast( + (void *)gKernelArgs.kernel_image); + //smp_init_other_cpus(); //serial_cleanup(); mmu_init_for_kernel(); @@ -81,8 +84,7 @@ platform_start_kernel(void) #warning M68K: stop ints - dprintf("kernel entry at %lx\n", - gKernelArgs.kernel_image.elf_header.e_entry); + dprintf("kernel entry at %lx\n", image->elf_header.e_entry); asm volatile ( "move.l %0,%%sp; " // move stack out of way @@ -97,7 +99,7 @@ platform_start_kernel(void) "move.l #0x0,-(%%sp);" // dummy retval for call to main "move.l %1,-(%%sp); " // this is the start address "rts; " // jump. - : : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry)); + : : "g" (args), "g" (image->elf_header.e_entry)); // Huston, we have a problem! diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 2944655a99..af2e64e5db 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -356,6 +356,9 @@ smp_cpu_ready(void) //TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu)); + preloaded_elf32_image *image = static_cast( + (void *)gKernelArgs.kernel_image); + // Important. Make sure supervisor threads can fault on read only pages... asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); asm("cld"); @@ -381,7 +384,7 @@ smp_cpu_ready(void) "pushl %2; " // this is the start address "ret; " // jump. : : "g" (curr_cpu), "g" (&gKernelArgs), - "g" (gKernelArgs.kernel_image.elf_header.e_entry)); + "g" (image->elf_header.e_entry)); // no where to return to return 0; diff --git a/src/system/boot/platform/bios_ia32/start.cpp b/src/system/boot/platform/bios_ia32/start.cpp index 6af13dd6da..82213afccb 100644 --- a/src/system/boot/platform/bios_ia32/start.cpp +++ b/src/system/boot/platform/bios_ia32/start.cpp @@ -82,6 +82,9 @@ platform_start_kernel(void) addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; + preloaded_elf32_image *image = static_cast( + (void *)gKernelArgs.kernel_image); + smp_init_other_cpus(); debug_cleanup(); mmu_init_for_kernel(); @@ -91,8 +94,7 @@ platform_start_kernel(void) smp_boot_other_cpus(); - dprintf("kernel entry at %lx\n", - gKernelArgs.kernel_image.elf_header.e_entry); + dprintf("kernel entry at %lx\n", image->elf_header.e_entry); asm("movl %0, %%eax; " // move stack out of way "movl %%eax, %%esp; " @@ -102,7 +104,7 @@ platform_start_kernel(void) "pushl $0x0;" // dummy retval for call to main "pushl %1; " // this is the start address "ret; " // jump. - : : "g" (args), "g" (gKernelArgs.kernel_image.elf_header.e_entry)); + : : "g" (args), "g" (image->elf_header.e_entry)); panic("kernel returned!\n"); } diff --git a/src/system/boot/platform/cfe/start.cpp b/src/system/boot/platform/cfe/start.cpp index 64309c2807..20e56a4198 100644 --- a/src/system/boot/platform/cfe/start.cpp +++ b/src/system/boot/platform/cfe/start.cpp @@ -60,7 +60,10 @@ clear_bss(void) extern "C" void platform_start_kernel(void) { - addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry; + preloaded_elf32_image* image = static_cast( + (void*)gKernelArgs.kernel_image); + + addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; diff --git a/src/system/boot/platform/openfirmware/start.cpp b/src/system/boot/platform/openfirmware/start.cpp index e297900d5f..d895caabcc 100644 --- a/src/system/boot/platform/openfirmware/start.cpp +++ b/src/system/boot/platform/openfirmware/start.cpp @@ -95,7 +95,10 @@ determine_machine(void) extern "C" void platform_start_kernel(void) { - addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry; + preloaded_elf32_image* image = static_cast( + (void*)gKernelArgs.kernel_image); + + addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; diff --git a/src/system/boot/platform/u-boot/start.cpp b/src/system/boot/platform/u-boot/start.cpp index 9b87c906f4..ffde980117 100644 --- a/src/system/boot/platform/u-boot/start.cpp +++ b/src/system/boot/platform/u-boot/start.cpp @@ -90,7 +90,10 @@ abort(void) extern "C" void platform_start_kernel(void) { - addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry; + preloaded_elf32_image *image = static_cast( + (void *)gKernelArgs.kernel_image); + + addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; @@ -99,8 +102,7 @@ platform_start_kernel(void) mmu_init_for_kernel(); // smp_boot_other_cpus(); - dprintf("kernel entry at %lx\n", - gKernelArgs.kernel_image.elf_header.e_entry); + dprintf("kernel entry at %lx\n", kernelEntry); status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); diff --git a/src/system/kernel/arch/arm/arch_elf.cpp b/src/system/kernel/arch/arm/arch_elf.cpp index a64d0fae5a..62fc17efd5 100644 --- a/src/system/kernel/arch/arm/arch_elf.cpp +++ b/src/system/kernel/arch/arm/arch_elf.cpp @@ -164,7 +164,7 @@ is_in_image(struct elf_image_info *image, addr_t address) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rel(struct preloaded_image *image, +boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, struct Elf32_Rel *rel, int relLength) #else int @@ -308,7 +308,7 @@ write_8_check(addr_t P, Elf32_Word value) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rela(struct preloaded_image *image, +boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, struct Elf32_Rela *rel, int rel_len) #else int diff --git a/src/system/kernel/arch/m68k/arch_elf.cpp b/src/system/kernel/arch/m68k/arch_elf.cpp index 7c96746802..2251f030dd 100644 --- a/src/system/kernel/arch/m68k/arch_elf.cpp +++ b/src/system/kernel/arch/m68k/arch_elf.cpp @@ -76,7 +76,7 @@ static const char *kRelocations[] = { #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rel(struct preloaded_image *image, +boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, struct Elf32_Rel *rel, int rel_len) #else int @@ -137,7 +137,7 @@ write_8_check(addr_t P, Elf32_Word value) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rela(struct preloaded_image *image, +boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, struct Elf32_Rela *rel, int rel_len) #else int diff --git a/src/system/kernel/arch/mipsel/arch_elf.cpp b/src/system/kernel/arch/mipsel/arch_elf.cpp index 6339b99c0d..f44206cd22 100644 --- a/src/system/kernel/arch/mipsel/arch_elf.cpp +++ b/src/system/kernel/arch/mipsel/arch_elf.cpp @@ -22,7 +22,7 @@ #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rel(struct preloaded_image *image, +boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, struct Elf32_Rel *rel, int rel_len) #else int @@ -83,7 +83,7 @@ write_8_check(addr_t P, Elf32_Word value) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rela(struct preloaded_image *image, +boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, struct Elf32_Rela *rel, int rel_len) #else int diff --git a/src/system/kernel/arch/ppc/arch_elf.cpp b/src/system/kernel/arch/ppc/arch_elf.cpp index 2cd675a793..75f6728f5b 100644 --- a/src/system/kernel/arch/ppc/arch_elf.cpp +++ b/src/system/kernel/arch/ppc/arch_elf.cpp @@ -21,7 +21,7 @@ #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rel(struct preloaded_image *image, +boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, struct Elf32_Rel *rel, int rel_len) #else int @@ -115,7 +115,7 @@ ha(Elf32_Word value) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rela(struct preloaded_image *image, +boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, struct Elf32_Rela *rel, int rel_len) #else int diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index 978ee9cb35..df6cebe250 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -56,7 +56,7 @@ is_in_image(struct elf_image_info *image, addr_t address) #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rel(struct preloaded_image *image, +boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, struct Elf32_Rel *rel, int relLength) #else int @@ -167,7 +167,7 @@ arch_elf_relocate_rel(struct elf_image_info *image, #ifdef _BOOT_MODE status_t -boot_arch_elf_relocate_rela(struct preloaded_image *image, +boot_arch_elf_relocate_rela(struct preloaded_elf32_image *image, struct Elf32_Rela *rel, int relLength) #else int diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index 2274f721d8..9d41ee1580 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -1418,7 +1418,7 @@ legacy_driver_add_preloaded(kernel_args* args) status = add_driver(imagePath.Path(), image->id); if (status != B_OK) { dprintf("legacy_driver_add_preloaded: Failed to add \"%s\": %s\n", - image->name, strerror(status)); + (char *)image->name, strerror(status)); unload_kernel_add_on(image->id); } } diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 64dd51aec4..f8c4e21f10 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -1245,7 +1245,7 @@ error1: static status_t -insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel) +insert_preloaded_image(struct preloaded_elf32_image *preloadedImage, bool kernel) { status_t status; @@ -1260,8 +1260,14 @@ insert_preloaded_image(struct preloaded_image *preloadedImage, bool kernel) image->name = strdup(preloadedImage->name); image->dynamic_section = preloadedImage->dynamic_section.start; - image->text_region = preloadedImage->text_region; - image->data_region = preloadedImage->data_region; + image->text_region.id = preloadedImage->text_region.id; + image->text_region.start = preloadedImage->text_region.start; + image->text_region.size = preloadedImage->text_region.size; + image->text_region.delta = preloadedImage->text_region.delta; + image->data_region.id = preloadedImage->data_region.id; + image->data_region.start = preloadedImage->data_region.start; + image->data_region.size = preloadedImage->data_region.size; + image->data_region.delta = preloadedImage->data_region.delta; status = elf_parse_dynamic_section(image); if (status != B_OK) @@ -2468,12 +2474,15 @@ elf_init(kernel_args *args) // Build a image structure for the kernel, which has already been loaded. // The preloaded_images were already prepared by the VM. - if (insert_preloaded_image(&args->kernel_image, true) < B_OK) + image = args->kernel_image; + if (insert_preloaded_image(static_cast( + image), true) < B_OK) panic("could not create kernel image.\n"); // Build image structures for all preloaded images. for (image = args->preloaded_images; image != NULL; image = image->next) - insert_preloaded_image(image, false); + insert_preloaded_image(static_cast( + image), false); add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address"); @@ -2589,4 +2598,4 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, return B_OK; } -#endif \ No newline at end of file +#endif diff --git a/src/system/kernel/module.cpp b/src/system/kernel/module.cpp index 202fb7c239..a2b5157cba 100644 --- a/src/system/kernel/module.cpp +++ b/src/system/kernel/module.cpp @@ -1805,7 +1805,7 @@ module_init(kernel_args* args) for (image = args->preloaded_images; image != NULL; image = image->next) { status_t status = register_preloaded_module_image(image); if (status != B_OK && image->is_module) { - dprintf("Could not register image \"%s\": %s\n", image->name, + dprintf("Could not register image \"%s\": %s\n", (char *)image->name, strerror(status)); } } diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 783872f5e5..858985ec12 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3537,9 +3537,13 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size) } +// TODO x86_64: hardcoding elf32 is temporary. static void -create_preloaded_image_areas(struct preloaded_image* image) +create_preloaded_image_areas(struct preloaded_elf32_image* image) { +#ifdef __x86_64__ + panic("fix this"); +#else char name[B_OS_NAME_LENGTH]; void* address; int32 length; @@ -3570,6 +3574,7 @@ create_preloaded_image_areas(struct preloaded_image* image) image->data_region.id = create_area(name, &address, B_EXACT_ADDRESS, PAGE_ALIGN(image->data_region.size), B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); +#endif } @@ -3842,11 +3847,13 @@ vm_init(kernel_args* args) allocate_kernel_args(args); - create_preloaded_image_areas(&args->kernel_image); + create_preloaded_image_areas(static_cast( + (void*)args->kernel_image)); // allocate areas for preloaded images for (image = args->preloaded_images; image != NULL; image = image->next) - create_preloaded_image_areas(image); + create_preloaded_image_areas( + static_cast(image)); // allocate kernel stacks for (i = 0; i < args->num_cpus; i++) { From 3a2a3367dc9bec2a5fbcd4ac849da6ac65e74e79 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 22 Jun 2012 19:55:38 +0100 Subject: [PATCH 030/273] Support static_cast on FixedWidthPointer. --- headers/private/kernel/util/FixedWidthPointer.h | 17 ++++++++++++++--- src/system/boot/platform/amiga_m68k/start.cpp | 2 +- src/system/boot/platform/atari_m68k/start.cpp | 2 +- src/system/boot/platform/bios_ia32/smp.cpp | 2 +- src/system/boot/platform/bios_ia32/start.cpp | 2 +- src/system/boot/platform/cfe/start.cpp | 2 +- src/system/boot/platform/openfirmware/start.cpp | 2 +- src/system/boot/platform/u-boot/start.cpp | 2 +- 8 files changed, 21 insertions(+), 10 deletions(-) diff --git a/headers/private/kernel/util/FixedWidthPointer.h b/headers/private/kernel/util/FixedWidthPointer.h index 56d88afaef..7024b65292 100644 --- a/headers/private/kernel/util/FixedWidthPointer.h +++ b/headers/private/kernel/util/FixedWidthPointer.h @@ -22,17 +22,28 @@ class FixedWidthPointer { public: operator Type*() const { - return (Type *)(addr_t)fValue; + return (Type*)(addr_t)fValue; + } + + template + operator OtherType*() const + { + return static_cast((Type*)(addr_t)fValue); } Type& operator*() const { - return *(Type *)*this; + return *((Type*)(addr_t)fValue); } Type* operator->() const { - return *this; + return (Type*)(addr_t)fValue; + } + + Type& operator[](size_t i) const + { + return ((Type*)(addr_t)fValue)[i]; } FixedWidthPointer& operator=(const FixedWidthPointer& p) diff --git a/src/system/boot/platform/amiga_m68k/start.cpp b/src/system/boot/platform/amiga_m68k/start.cpp index 2356f85fb4..490778e2dd 100644 --- a/src/system/boot/platform/amiga_m68k/start.cpp +++ b/src/system/boot/platform/amiga_m68k/start.cpp @@ -75,7 +75,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - (void *)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); //smp_init_other_cpus(); //serial_cleanup(); diff --git a/src/system/boot/platform/atari_m68k/start.cpp b/src/system/boot/platform/atari_m68k/start.cpp index e03ee4165c..76fd2c733a 100644 --- a/src/system/boot/platform/atari_m68k/start.cpp +++ b/src/system/boot/platform/atari_m68k/start.cpp @@ -75,7 +75,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - (void *)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); //smp_init_other_cpus(); //serial_cleanup(); diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index af2e64e5db..d4364f7d9d 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -357,7 +357,7 @@ smp_cpu_ready(void) //TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu)); preloaded_elf32_image *image = static_cast( - (void *)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); // Important. Make sure supervisor threads can fault on read only pages... asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); diff --git a/src/system/boot/platform/bios_ia32/start.cpp b/src/system/boot/platform/bios_ia32/start.cpp index 82213afccb..41284f608c 100644 --- a/src/system/boot/platform/bios_ia32/start.cpp +++ b/src/system/boot/platform/bios_ia32/start.cpp @@ -83,7 +83,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - (void *)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); smp_init_other_cpus(); debug_cleanup(); diff --git a/src/system/boot/platform/cfe/start.cpp b/src/system/boot/platform/cfe/start.cpp index 20e56a4198..8d72532030 100644 --- a/src/system/boot/platform/cfe/start.cpp +++ b/src/system/boot/platform/cfe/start.cpp @@ -61,7 +61,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image* image = static_cast( - (void*)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start diff --git a/src/system/boot/platform/openfirmware/start.cpp b/src/system/boot/platform/openfirmware/start.cpp index d895caabcc..d1729ad3c6 100644 --- a/src/system/boot/platform/openfirmware/start.cpp +++ b/src/system/boot/platform/openfirmware/start.cpp @@ -96,7 +96,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image* image = static_cast( - (void*)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start diff --git a/src/system/boot/platform/u-boot/start.cpp b/src/system/boot/platform/u-boot/start.cpp index ffde980117..0f1fa00fcc 100644 --- a/src/system/boot/platform/u-boot/start.cpp +++ b/src/system/boot/platform/u-boot/start.cpp @@ -91,7 +91,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image *image = static_cast( - (void *)gKernelArgs.kernel_image); + gKernelArgs.kernel_image); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop From ccadfaeeb577eb5f129adcc1441b92aaf9f5e443 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 23 Jun 2012 12:05:16 +0100 Subject: [PATCH 031/273] Changed the boot ELF code to use templates and added ELF64 support. The actual implementation of the ELF loading methods have been put into an ELFLoader template class that takes a single template parameter, which is a structure containing all the necessary ELF typedefs. It's a bit verbose, but I thought it was a neater solution than using a bunch of standalone functions with a huge number of template parameters. There is no change to code outside of elf.cpp, the ELF32/ELF64 differences are handled internally. --- headers/private/kernel/boot/arch.h | 21 +- headers/private/kernel/boot/elf.h | 19 +- headers/private/system/elf_common.h | 8 - src/system/boot/loader/Jamfile | 4 +- src/system/boot/loader/elf.cpp | 662 ++++++++++++++++------------ src/system/boot/loader/elf.h | 7 +- 6 files changed, 415 insertions(+), 306 deletions(-) diff --git a/headers/private/kernel/boot/arch.h b/headers/private/kernel/boot/arch.h index 8642efe57e..2f4be42982 100644 --- a/headers/private/kernel/boot/arch.h +++ b/headers/private/kernel/boot/arch.h @@ -5,24 +5,21 @@ #ifndef KERNEL_BOOT_ARCH_H #define KERNEL_BOOT_ARCH_H + #include #include -#ifdef __cplusplus -extern "C" { -#endif - /* ELF support */ -extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image *image, - struct Elf32_Rel *rel, int rel_len); -extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image *image, - struct Elf32_Rela *rel, int rel_len); +extern status_t boot_arch_elf_relocate_rel(preloaded_elf32_image* image, + struct Elf32_Rel* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rel(preloaded_elf64_image* image, + struct Elf64_Rel* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rela(preloaded_elf32_image* image, + struct Elf32_Rela* rel, int rel_len); +extern status_t boot_arch_elf_relocate_rela(preloaded_elf64_image* image, + struct Elf64_Rela* rel, int rel_len); -#ifdef __cplusplus -} -#endif - #endif /* KERNEL_BOOT_ARCH_H */ diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 1ef93c2b16..6c07ebcc35 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -1,7 +1,8 @@ /* -** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the OpenBeOS License. -*/ + * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the OpenBeOS License. + */ #ifndef KERNEL_BOOT_ELF_H #define KERNEL_BOOT_ELF_H @@ -76,15 +77,11 @@ struct preloaded_elf64_image : public preloaded_image { FixedWidthPointer debug_symbols; } _PACKED; -#ifdef __cplusplus -extern "C" { -#endif -extern status_t boot_elf_resolve_symbol(struct preloaded_elf32_image *image, - struct Elf32_Sym *symbol, addr_t *symbolAddress); +extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, + struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress); +extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, + struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress); -#ifdef __cplusplus -} -#endif #endif /* KERNEL_BOOT_ELF_H */ diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h index 6a85bf2012..61eb43f67e 100644 --- a/headers/private/system/elf_common.h +++ b/headers/private/system/elf_common.h @@ -15,14 +15,6 @@ #include -typedef uint32 Elf32_Addr; -typedef uint16 Elf32_Half; -typedef uint32 Elf32_Off; -typedef int32 Elf32_Sword; -typedef uint32 Elf32_Word; - -typedef Elf32_Half Elf32_Versym; - /*** ELF header ***/ #define EI_NIDENT 16 diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index f325c3279f..c9486992e9 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -39,7 +39,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86_64\\\" - BOOT_SUPPORT_ELF64 + #BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI @@ -50,7 +50,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86\\\" - BOOT_SUPPORT_ELF64 + #BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 841966b979..f54e96b96d 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -30,233 +30,114 @@ static bool sLoadElfSymbols = true; -void -elf_init() -{ -// TODO: This cannot work, since the driver settings are loaded *after* the -// kernel has been loaded successfully. -#if 0 - void *settings = load_driver_settings("kernel"); - if (settings == NULL) - return; +// #pragma mark - Generic ELF loader - sLoadElfSymbols = !get_driver_boolean_parameter(settings, "load_symbols", - false, false); - unload_driver_settings(settings); + +template +class ELFLoader { +private: + typedef typename Class::ImageType ImageType; + typedef typename Class::RegionType RegionType; + typedef typename Class::EhdrType EhdrType; + typedef typename Class::PhdrType PhdrType; + typedef typename Class::ShdrType ShdrType; + typedef typename Class::DynType DynType; + typedef typename Class::SymType SymType; + typedef typename Class::RelType RelType; + typedef typename Class::RelaType RelaType; + +public: + static status_t Create(int fd, preloaded_image** _image); + static status_t Load(int fd, preloaded_image* image); + static status_t Relocate(preloaded_image* image); + +private: + static status_t _LoadSymbolTable(int fd, ImageType* image); + static status_t _ParseDynamicSection(ImageType* image); +}; + + +struct ELF32Class { + static const uint8 kIdentClass = ELFCLASS32; + + typedef preloaded_elf32_image ImageType; + typedef elf32_region RegionType; + typedef Elf32_Ehdr EhdrType; + typedef Elf32_Phdr PhdrType; + typedef Elf32_Shdr ShdrType; + typedef Elf32_Dyn DynType; + typedef Elf32_Sym SymType; + typedef Elf32_Rel RelType; + typedef Elf32_Rela RelaType; +}; + +typedef ELFLoader ELF32Loader; + + +#ifdef BOOT_SUPPORT_ELF64 +struct ELF64Class { + static const uint8 kIdentClass = ELFCLASS64; + + typedef preloaded_elf64_image ImageType; + typedef elf64_region RegionType; + typedef Elf64_Ehdr EhdrType; + typedef Elf64_Phdr PhdrType; + typedef Elf64_Shdr ShdrType; + typedef Elf64_Dyn DynType; + typedef Elf64_Sym SymType; + typedef Elf64_Rel RelType; + typedef Elf64_Rela RelaType; +}; + +typedef ELFLoader ELF64Loader; #endif -} -static status_t -verify_elf_header(struct Elf32_Ehdr &header) +template +/*static*/ status_t +ELFLoader::Create(int fd, preloaded_image** _image) { - if (memcmp(header.e_ident, ELF_MAGIC, 4) != 0 - || header.e_ident[4] != ELFCLASS32 - || header.e_phoff == 0 - || !header.IsHostEndian() - || header.e_phentsize != sizeof(struct Elf32_Phdr)) - return B_BAD_TYPE; - - return B_OK; -} - - -static status_t -elf_parse_dynamic_section(preloaded_elf32_image *image) -{ - image->syms = 0; - image->rel = 0; - image->rel_len = 0; - image->rela = 0; - image->rela_len = 0; - image->pltrel = 0; - image->pltrel_len = 0; - image->pltrel_type = 0; - - struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_section.start; - if (!d) - return B_ERROR; - - for (int i = 0; d[i].d_tag != DT_NULL; i++) { - switch (d[i].d_tag) { - case DT_HASH: - case DT_STRTAB: - break; - case DT_SYMTAB: - image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_REL: - image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_RELSZ: - image->rel_len = d[i].d_un.d_val; - break; - case DT_RELA: - image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_RELASZ: - image->rela_len = d[i].d_un.d_val; - break; - case DT_JMPREL: - image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr - + image->text_region.delta); - break; - case DT_PLTRELSZ: - image->pltrel_len = d[i].d_un.d_val; - break; - case DT_PLTREL: - image->pltrel_type = d[i].d_un.d_val; - break; - - default: - continue; - } - } - - // lets make sure we found all the required sections - if (image->syms == NULL) - return B_ERROR; - - return B_OK; -} - - -static status_t -load_elf_symbol_table(int fd, preloaded_elf32_image *image) -{ - struct Elf32_Ehdr &elfHeader = image->elf_header; - Elf32_Sym *symbolTable = NULL; - Elf32_Shdr *stringHeader = NULL; - uint32 numSymbols = 0; - char *stringTable; - status_t status; - - // get section headers - - ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize; - Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size); - if (sectionHeaders == NULL) { - dprintf("error allocating space for section headers\n"); - return B_NO_MEMORY; - } - - ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size); - if (length < size) { - TRACE(("error reading in program headers\n")); - status = B_ERROR; - goto error1; - } - - // find symbol table in section headers - - for (int32 i = 0; i < elfHeader.e_shnum; i++) { - if (sectionHeaders[i].sh_type == SHT_SYMTAB) { - stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; - - if (stringHeader->sh_type != SHT_STRTAB) { - TRACE(("doesn't link to string table\n")); - status = B_BAD_DATA; - goto error1; - } - - // read in symbol table - symbolTable = (Elf32_Sym *)kernel_args_malloc( - size = sectionHeaders[i].sh_size); - if (symbolTable == NULL) { - status = B_NO_MEMORY; - goto error1; - } - - length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, - size); - if (length < size) { - TRACE(("error reading in symbol table\n")); - status = B_ERROR; - goto error1; - } - - numSymbols = size / sizeof(Elf32_Sym); - break; - } - } - - if (symbolTable == NULL) { - TRACE(("no symbol table\n")); - status = B_BAD_VALUE; - goto error1; - } - - // read in string table - - stringTable = (char *)kernel_args_malloc(size = stringHeader->sh_size); - if (stringTable == NULL) { - status = B_NO_MEMORY; - goto error2; - } - - length = read_pos(fd, stringHeader->sh_offset, stringTable, size); - if (length < size) { - TRACE(("error reading in string table\n")); - status = B_ERROR; - goto error3; - } - - TRACE(("loaded %ld debug symbols\n", numSymbols)); - - // insert tables into image - image->debug_symbols = symbolTable; - image->num_debug_symbols = numSymbols; - image->debug_string_table = stringTable; - image->debug_string_table_size = size; - - free(sectionHeaders); - return B_OK; - -error3: - kernel_args_free(stringTable); -error2: - kernel_args_free(symbolTable); -error1: - free(sectionHeaders); - - return status; -} - - -status_t -elf_load_image(int fd, preloaded_image **_image) -{ - size_t totalSize; - status_t status; - - TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); - - preloaded_elf32_image *image = (preloaded_elf32_image *)kernel_args_malloc( - sizeof(preloaded_elf32_image)); + ImageType* image = (ImageType*)kernel_args_malloc(sizeof(ImageType)); if (image == NULL) return B_NO_MEMORY; - struct Elf32_Ehdr &elfHeader = image->elf_header; + EhdrType& elfHeader = image->elf_header; - ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(Elf32_Ehdr)); - if (length < (ssize_t)sizeof(Elf32_Ehdr)) { + ssize_t length = read_pos(fd, 0, &elfHeader, sizeof(EhdrType)); + if (length < (ssize_t)sizeof(EhdrType)) { kernel_args_free(image); return B_BAD_TYPE; } - status = verify_elf_header(elfHeader); - if (status < B_OK) { + if (memcmp(elfHeader.e_ident, ELF_MAGIC, 4) != 0 + || elfHeader.e_ident[4] != Class::kIdentClass + || elfHeader.e_phoff == 0 + || !elfHeader.IsHostEndian() + || elfHeader.e_phentsize != sizeof(PhdrType)) { kernel_args_free(image); - return status; + return B_BAD_TYPE; } image->elf_class = elfHeader.e_ident[EI_CLASS]; + *_image = image; + return B_OK; +} + + +template +/*static*/ status_t +ELFLoader::Load(int fd, preloaded_image* _image) +{ + size_t totalSize; + ssize_t length; + status_t status; + + ImageType* image = static_cast(_image); + EhdrType& elfHeader = image->elf_header; + ssize_t size = elfHeader.e_phnum * elfHeader.e_phentsize; - Elf32_Phdr *programHeaders = (struct Elf32_Phdr *)malloc(size); + PhdrType* programHeaders = (PhdrType*)malloc(size); if (programHeaders == NULL) { dprintf("error allocating space for program headers\n"); status = B_NO_MEMORY; @@ -276,7 +157,7 @@ elf_load_image(int fd, preloaded_image **_image) image->text_region.size = 0; for (int32 i = 0; i < elfHeader.e_phnum; i++) { - Elf32_Phdr &header = programHeaders[i]; + PhdrType& header = programHeaders[i]; switch (header.p_type) { case PT_LOAD: @@ -294,7 +175,7 @@ elf_load_image(int fd, preloaded_image **_image) continue; } - elf32_region *region; + RegionType* region; if (header.IsReadWrite()) { if (image->data_region.size != 0) { dprintf("elf: rw already handled!\n"); @@ -327,8 +208,8 @@ elf_load_image(int fd, preloaded_image **_image) } // get the segment order - elf32_region *firstRegion; - elf32_region *secondRegion; + RegionType* firstRegion; + RegionType* secondRegion; if (image->text_region.start < image->data_region.start) { firstRegion = &image->text_region; secondRegion = &image->data_region; @@ -363,13 +244,13 @@ elf_load_image(int fd, preloaded_image **_image) // load program data - for (int i = 0; i < elfHeader.e_phnum; i++) { - Elf32_Phdr &header = programHeaders[i]; + for (int32 i = 0; i < elfHeader.e_phnum; i++) { + PhdrType& header = programHeaders[i]; if (header.p_type != PT_LOAD) continue; - elf32_region *region; + RegionType* region; if (header.IsReadWrite()) region = &image->data_region; else if (header.IsExecutable()) @@ -380,11 +261,11 @@ elf_load_image(int fd, preloaded_image **_image) TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz)); length = read_pos(fd, header.p_offset, - (void *)(region->start + (header.p_vaddr % B_PAGE_SIZE)), + (void*)(region->start + (header.p_vaddr % B_PAGE_SIZE)), header.p_filesz); if (length < (ssize_t)header.p_filesz) { status = B_BAD_DATA; - dprintf("error reading in seg %d\n", i); + dprintf("error reading in seg %ld\n", i); goto error2; } @@ -393,7 +274,7 @@ elf_load_image(int fd, preloaded_image **_image) uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz; if (offset < region->size) - memset((void *)(region->start + offset), 0, region->size - offset); + memset((void*)(region->start + offset), 0, region->size - offset); } // offset dynamic section, and program entry addresses by the delta of the @@ -406,16 +287,15 @@ elf_load_image(int fd, preloaded_image **_image) image->debug_string_table = NULL; if (sLoadElfSymbols) - load_elf_symbol_table(fd, image); + _LoadSymbolTable(fd, image); free(programHeaders); - *_image = image; return B_OK; error2: if (image->text_region.start != 0) - platform_free_region((void *)image->text_region.start, totalSize); + platform_free_region((void*)image->text_region.start, totalSize); error1: free(programHeaders); kernel_args_free(image); @@ -424,10 +304,270 @@ error1: } -status_t -elf_load_image(Directory *directory, const char *path) +template +/*static*/ status_t +ELFLoader::Relocate(preloaded_image* _image) { - preloaded_image *image; + ImageType* image = static_cast(_image); + + status_t status = _ParseDynamicSection(image); + if (status != B_OK) + return status; + + // deal with the rels first + if (image->rel) { + TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(RelType))); + + status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); + if (status < B_OK) + return status; + } + + if (image->pltrel) { + TRACE(("total %i plt-relocs\n", + image->pltrel_len / (int)sizeof(RelType))); + + RelType* pltrel = image->pltrel; + if (image->pltrel_type == DT_REL) { + status = boot_arch_elf_relocate_rel(image, pltrel, + image->pltrel_len); + } else { + status = boot_arch_elf_relocate_rela(image, (RelaType *)pltrel, + image->pltrel_len); + } + if (status < B_OK) + return status; + } + + if (image->rela) { + TRACE(("total %i rela relocs\n", + image->rela_len / (int)sizeof(RelaType))); + status = boot_arch_elf_relocate_rela(image, image->rela, + image->rela_len); + if (status < B_OK) + return status; + } + + return B_OK; +} + + +template +/*static*/ status_t +ELFLoader::_LoadSymbolTable(int fd, ImageType* image) +{ + EhdrType& elfHeader = image->elf_header; + SymType* symbolTable = NULL; + ShdrType* stringHeader = NULL; + uint32 numSymbols = 0; + char* stringTable; + status_t status; + + // get section headers + + ssize_t size = elfHeader.e_shnum * elfHeader.e_shentsize; + ShdrType* sectionHeaders = (ShdrType*)malloc(size); + if (sectionHeaders == NULL) { + dprintf("error allocating space for section headers\n"); + return B_NO_MEMORY; + } + + ssize_t length = read_pos(fd, elfHeader.e_shoff, sectionHeaders, size); + if (length < size) { + TRACE(("error reading in program headers\n")); + status = B_ERROR; + goto error1; + } + + // find symbol table in section headers + + for (int32 i = 0; i < elfHeader.e_shnum; i++) { + if (sectionHeaders[i].sh_type == SHT_SYMTAB) { + stringHeader = §ionHeaders[sectionHeaders[i].sh_link]; + + if (stringHeader->sh_type != SHT_STRTAB) { + TRACE(("doesn't link to string table\n")); + status = B_BAD_DATA; + goto error1; + } + + // read in symbol table + size = sectionHeaders[i].sh_size; + symbolTable = (SymType*)kernel_args_malloc(size); + if (symbolTable == NULL) { + status = B_NO_MEMORY; + goto error1; + } + + length = read_pos(fd, sectionHeaders[i].sh_offset, symbolTable, + size); + if (length < size) { + TRACE(("error reading in symbol table\n")); + status = B_ERROR; + goto error1; + } + + numSymbols = size / sizeof(SymType); + break; + } + } + + if (symbolTable == NULL) { + TRACE(("no symbol table\n")); + status = B_BAD_VALUE; + goto error1; + } + + // read in string table + + size = stringHeader->sh_size; + stringTable = (char*)kernel_args_malloc(size); + if (stringTable == NULL) { + status = B_NO_MEMORY; + goto error2; + } + + length = read_pos(fd, stringHeader->sh_offset, stringTable, size); + if (length < size) { + TRACE(("error reading in string table\n")); + status = B_ERROR; + goto error3; + } + + TRACE(("loaded %ld debug symbols\n", numSymbols)); + + // insert tables into image + image->debug_symbols = symbolTable; + image->num_debug_symbols = numSymbols; + image->debug_string_table = stringTable; + image->debug_string_table_size = size; + + free(sectionHeaders); + return B_OK; + +error3: + kernel_args_free(stringTable); +error2: + kernel_args_free(symbolTable); +error1: + free(sectionHeaders); + + return status; +} + + +template +/*static*/ status_t +ELFLoader::_ParseDynamicSection(ImageType* image) +{ + image->syms = 0; + image->rel = 0; + image->rel_len = 0; + image->rela = 0; + image->rela_len = 0; + image->pltrel = 0; + image->pltrel_len = 0; + image->pltrel_type = 0; + + DynType* d = (DynType*)image->dynamic_section.start; + if (!d) + return B_ERROR; + + for (int i = 0; d[i].d_tag != DT_NULL; i++) { + switch (d[i].d_tag) { + case DT_HASH: + case DT_STRTAB: + break; + case DT_SYMTAB: + image->syms = (SymType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_REL: + image->rel = (RelType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_RELSZ: + image->rel_len = d[i].d_un.d_val; + break; + case DT_RELA: + image->rela = (RelaType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_RELASZ: + image->rela_len = d[i].d_un.d_val; + break; + case DT_JMPREL: + image->pltrel = (RelType*)(d[i].d_un.d_ptr + + image->text_region.delta); + break; + case DT_PLTRELSZ: + image->pltrel_len = d[i].d_un.d_val; + break; + case DT_PLTREL: + image->pltrel_type = d[i].d_un.d_val; + break; + + default: + continue; + } + } + + // lets make sure we found all the required sections + if (image->syms == NULL) + return B_ERROR; + + return B_OK; +} + + +// #pragma mark - + + +void +elf_init() +{ +// TODO: This cannot work, since the driver settings are loaded *after* the +// kernel has been loaded successfully. +#if 0 + void *settings = load_driver_settings("kernel"); + if (settings == NULL) + return; + + sLoadElfSymbols = !get_driver_boolean_parameter(settings, "load_symbols", + false, false); + unload_driver_settings(settings); +#endif +} + + +status_t +elf_load_image(int fd, preloaded_image** _image) +{ + status_t status; + + TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); + +#if BOOT_SUPPORT_ELF64 + status = ELF64Loader::Create(fd, _image); + if (status == B_OK) { + return ELF64Loader::Load(fd, *_image); + } else if (status == B_BAD_TYPE) { +#endif + status = ELF32Loader::Create(fd, _image); + if (status == B_OK) + return ELF32Loader::Load(fd, *_image); +#if BOOT_SUPPORT_ELF64 + } +#endif + + return status; +} + + +status_t +elf_load_image(Directory* directory, const char* path) +{ + preloaded_image* image; TRACE(("elf_load_image(directory = %p, \"%s\")\n", directory, path)); @@ -469,56 +609,20 @@ elf_load_image(Directory *directory, const char *path) status_t -elf_relocate_image(preloaded_image *_image) +elf_relocate_image(preloaded_image* image) { - preloaded_elf32_image *image = static_cast(_image); - - status_t status = elf_parse_dynamic_section(image); - if (status != B_OK) - return status; - - // deal with the rels first - if (image->rel) { - TRACE(("total %i relocs\n", - image->rel_len / (int)sizeof(struct Elf32_Rel))); - - status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); - if (status < B_OK) - return status; - } - - if (image->pltrel) { - TRACE(("total %i plt-relocs\n", - image->pltrel_len / (int)sizeof(struct Elf32_Rel))); - - struct Elf32_Rel *pltrel = image->pltrel; - if (image->pltrel_type == DT_REL) { - status = boot_arch_elf_relocate_rel(image, pltrel, - image->pltrel_len); - } else { - status = boot_arch_elf_relocate_rela(image, - (struct Elf32_Rela *)pltrel, image->pltrel_len); - } - if (status < B_OK) - return status; - } - - if (image->rela) { - TRACE(("total %i rela relocs\n", - image->rela_len / (int)sizeof(struct Elf32_Rela))); - status = boot_arch_elf_relocate_rela(image, image->rela, - image->rela_len); - if (status < B_OK) - return status; - } - - return B_OK; +#ifdef BOOT_SUPPORT_ELF64 + if (image->elf_class == ELFCLASS64) + return ELF64Loader::Relocate(image); + else +#endif + return ELF32Loader::Relocate(image); } -status_t -boot_elf_resolve_symbol(struct preloaded_elf32_image *image, - struct Elf32_Sym *symbol, addr_t *symbolAddress) +template +inline status_t +resolve_symbol(ImageType* image, SymType* symbol, AddrType* symbolAddress) { switch (symbol->st_shndx) { case SHN_UNDEF: @@ -538,3 +642,21 @@ boot_elf_resolve_symbol(struct preloaded_elf32_image *image, return B_NO_ERROR; } } + + +status_t +boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, + Elf32_Addr* symbolAddress) +{ + return resolve_symbol(image, symbol, symbolAddress); +} + + +#ifdef BOOT_SUPPORT_ELF64 +status_t +boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol, + Elf64_Addr* symbolAddress) +{ + return resolve_symbol(image, symbol, symbolAddress); +} +#endif diff --git a/src/system/boot/loader/elf.h b/src/system/boot/loader/elf.h index 9f5358a71f..9a0e610936 100644 --- a/src/system/boot/loader/elf.h +++ b/src/system/boot/loader/elf.h @@ -11,9 +11,10 @@ extern void elf_init(); -extern status_t elf_load_image(Directory *directory, const char *path); -extern status_t elf_load_image(int fd, preloaded_image **_image); +extern status_t elf_load_image(Directory* directory, const char* path); +extern status_t elf_load_image(int fd, preloaded_image** _image); + +extern status_t elf_relocate_image(preloaded_image* image); -extern status_t elf_relocate_image(preloaded_image *image); #endif /* LOADER_ELF_H */ From 69a8b95491c160f03a5b0dab0fa8d1899fe42d4b Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 23 Jun 2012 23:49:32 +0200 Subject: [PATCH 032/273] FixedWidthPointer: Fix ==/!= operators, remove OtherType casts * FixedWidthPointer: - operators ==/!=: Change second operand type from void* to const Type*. Also add non-const version to resolve ambiguity warning when comparing with non-const pointer. - Add Pointer() getter. - Remove templatized cast operators. They are nice for casting the pointer directly to another pointer type, but result in ambiguity. * Make preloaded_image::debug_string_table non-const. Avoids clashes of the const and non-coast FixedWidthPointer comparison operators. A cleaner (but more verbose) solution would be to spezialize FixedWidthPointer for const types. --- headers/private/kernel/boot/elf.h | 2 +- .../private/kernel/util/FixedWidthPointer.h | 42 +++++++++++++------ src/system/boot/loader/menu.cpp | 8 ++-- src/system/boot/platform/bios_ia32/smp.cpp | 2 +- src/system/boot/platform/bios_ia32/start.cpp | 2 +- .../kernel/arch/x86/timers/x86_hpet.cpp | 2 +- src/system/kernel/debug/debug.cpp | 6 ++- 7 files changed, 42 insertions(+), 22 deletions(-) diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 6c07ebcc35..88514d9c92 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -32,7 +32,7 @@ struct preloaded_image { uint8 elf_class; addr_range dynamic_section; - FixedWidthPointer debug_string_table; + FixedWidthPointer debug_string_table; uint32 num_debug_symbols; uint32 debug_string_table_size; diff --git a/headers/private/kernel/util/FixedWidthPointer.h b/headers/private/kernel/util/FixedWidthPointer.h index 7024b65292..03295323c1 100644 --- a/headers/private/kernel/util/FixedWidthPointer.h +++ b/headers/private/kernel/util/FixedWidthPointer.h @@ -20,30 +20,29 @@ template class FixedWidthPointer { public: - operator Type*() const + Type * Pointer() const { return (Type*)(addr_t)fValue; } - template - operator OtherType*() const + operator Type*() const { - return static_cast((Type*)(addr_t)fValue); + return Pointer(); } Type& operator*() const { - return *((Type*)(addr_t)fValue); + return *Pointer(); } Type* operator->() const { - return (Type*)(addr_t)fValue; + return Pointer(); } Type& operator[](size_t i) const { - return ((Type*)(addr_t)fValue)[i]; + return Pointer()[i]; } FixedWidthPointer& operator=(const FixedWidthPointer& p) @@ -85,15 +84,14 @@ private: template<> class FixedWidthPointer { public: - operator void*() const + void * Pointer() const { return (void*)(addr_t)fValue; } - template - operator OtherType*() const + operator void*() const { - return (OtherType*)(addr_t)fValue; + return Pointer(); } FixedWidthPointer& operator=(const FixedWidthPointer& p) @@ -122,16 +120,34 @@ private: uint64 fValue; } _PACKED; + template inline bool -operator==(const FixedWidthPointer& a, void* b) +operator==(const FixedWidthPointer& a, const Type* b) { return a.Get() == (addr_t)b; } + template inline bool -operator!=(const FixedWidthPointer& a, void* b) +operator!=(const FixedWidthPointer& a, const Type* b) +{ + return a.Get() != (addr_t)b; +} + + +template +inline bool +operator==(const FixedWidthPointer& a, Type* b) +{ + return a.Get() == (addr_t)b; +} + + +template +inline bool +operator!=(const FixedWidthPointer& a, Type* b) { return a.Get() != (addr_t)b; } diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index 0397237359..fbb90d5427 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -534,7 +534,7 @@ debug_menu_display_current_log(Menu* menu, MenuItem* item) static bool debug_menu_display_previous_syslog(Menu* menu, MenuItem* item) { - ring_buffer* buffer = (ring_buffer*)gKernelArgs.debug_output; + ring_buffer* buffer = (ring_buffer*)gKernelArgs.debug_output.Pointer(); if (buffer == NULL) return true; @@ -595,7 +595,8 @@ save_previous_syslog_to_volume(Directory* directory) return fd; } - ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output; + ring_buffer* syslogBuffer + = (ring_buffer*)gKernelArgs.debug_output.Pointer(); iovec vecs[2]; int32 vecCount = ring_buffer_get_vecs(syslogBuffer, vecs); if (vecCount > 0) { @@ -899,7 +900,8 @@ add_debug_menu() "Displays the debug info the boot loader has logged."); } - ring_buffer* syslogBuffer = (ring_buffer*)gKernelArgs.debug_output; + ring_buffer* syslogBuffer + = (ring_buffer*)gKernelArgs.debug_output.Pointer(); if (syslogBuffer != NULL && ring_buffer_readable(syslogBuffer) > 0) { if (!currentLogItemVisible) menu->AddSeparatorItem(); diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index d4364f7d9d..4bc2402866 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -357,7 +357,7 @@ smp_cpu_ready(void) //TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu)); preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); // Important. Make sure supervisor threads can fault on read only pages... asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); diff --git a/src/system/boot/platform/bios_ia32/start.cpp b/src/system/boot/platform/bios_ia32/start.cpp index 41284f608c..b15d539ccc 100644 --- a/src/system/boot/platform/bios_ia32/start.cpp +++ b/src/system/boot/platform/bios_ia32/start.cpp @@ -83,7 +83,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); smp_init_other_cpus(); debug_cleanup(); diff --git a/src/system/kernel/arch/x86/timers/x86_hpet.cpp b/src/system/kernel/arch/x86/timers/x86_hpet.cpp index d5dfa48693..e25785cd58 100644 --- a/src/system/kernel/arch/x86/timers/x86_hpet.cpp +++ b/src/system/kernel/arch/x86/timers/x86_hpet.cpp @@ -221,7 +221,7 @@ hpet_init(struct kernel_args *args) return B_ERROR; if (sHPETRegs == NULL) { - sHPETRegs = (struct hpet_regs *)args->arch_args.hpet; + sHPETRegs = (struct hpet_regs *)args->arch_args.hpet.Pointer(); if (vm_map_physical_memory(B_SYSTEM_TEAM, "hpet", (void **)&sHPETRegs, B_EXACT_ADDRESS, B_PAGE_SIZE, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 791c827448..1b5d12df37 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -1401,8 +1401,10 @@ syslog_init_post_vm(struct kernel_args* args) sSyslogMessage->ident[0] = '\0'; //strcpy(sSyslogMessage->ident, "KERNEL"); - if (args->debug_output != NULL) - syslog_write((const char*)args->debug_output, args->debug_size, false); + if (args->debug_output != NULL) { + syslog_write((const char*)args->debug_output.Pointer(), + args->debug_size, false); + } char revisionBuffer[64]; length = snprintf(revisionBuffer, sizeof(revisionBuffer), From acda52f5e963b1c76fed2eca0409444cda4529b5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 15:48:03 +0100 Subject: [PATCH 033/273] Fixes for other platforms. --- src/system/boot/platform/amiga_m68k/start.cpp | 2 +- src/system/boot/platform/atari_m68k/start.cpp | 2 +- src/system/boot/platform/cfe/start.cpp | 2 +- src/system/boot/platform/openfirmware/start.cpp | 2 +- src/system/boot/platform/u-boot/start.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/system/boot/platform/amiga_m68k/start.cpp b/src/system/boot/platform/amiga_m68k/start.cpp index 490778e2dd..8881ca7209 100644 --- a/src/system/boot/platform/amiga_m68k/start.cpp +++ b/src/system/boot/platform/amiga_m68k/start.cpp @@ -75,7 +75,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); //smp_init_other_cpus(); //serial_cleanup(); diff --git a/src/system/boot/platform/atari_m68k/start.cpp b/src/system/boot/platform/atari_m68k/start.cpp index 76fd2c733a..c0f6503bcc 100644 --- a/src/system/boot/platform/atari_m68k/start.cpp +++ b/src/system/boot/platform/atari_m68k/start.cpp @@ -75,7 +75,7 @@ platform_start_kernel(void) = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); //smp_init_other_cpus(); //serial_cleanup(); diff --git a/src/system/boot/platform/cfe/start.cpp b/src/system/boot/platform/cfe/start.cpp index 8d72532030..b9a8dafb82 100644 --- a/src/system/boot/platform/cfe/start.cpp +++ b/src/system/boot/platform/cfe/start.cpp @@ -61,7 +61,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image* image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start diff --git a/src/system/boot/platform/openfirmware/start.cpp b/src/system/boot/platform/openfirmware/start.cpp index d1729ad3c6..0d983e8292 100644 --- a/src/system/boot/platform/openfirmware/start.cpp +++ b/src/system/boot/platform/openfirmware/start.cpp @@ -96,7 +96,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image* image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop = gKernelArgs.cpu_kstack[0].start diff --git a/src/system/boot/platform/u-boot/start.cpp b/src/system/boot/platform/u-boot/start.cpp index 0f1fa00fcc..a3b93bcc84 100644 --- a/src/system/boot/platform/u-boot/start.cpp +++ b/src/system/boot/platform/u-boot/start.cpp @@ -91,7 +91,7 @@ extern "C" void platform_start_kernel(void) { preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image); + gKernelArgs.kernel_image.Pointer()); addr_t kernelEntry = image->elf_header.e_entry; addr_t stackTop From 035825cdfcf0f778a4e87c7a216c14ab5e9b8116 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 17:19:48 +0100 Subject: [PATCH 034/273] Align the start of the kernel .data to a 2MB boundary, prevents ld from merging the text and data PHDRs. --- src/system/ldscripts/x86_64/kernel.ld | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/ldscripts/x86_64/kernel.ld b/src/system/ldscripts/x86_64/kernel.ld index 070379289a..1496cc7cae 100644 --- a/src/system/ldscripts/x86_64/kernel.ld +++ b/src/system/ldscripts/x86_64/kernel.ld @@ -28,8 +28,8 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - /* writable data */ - . = ALIGN(0x1000); + /* writable data */ + . = ALIGN (0x200000); __data_start = .; .data : { *(.data .data.* .gnu.linkonce.d.*) } From c2656eb9bd735878c33f979c273ba59a1f96cc09 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 17:51:05 +0100 Subject: [PATCH 035/273] Improved elf_load_image() a bit. After enabling BOOT_SUPPORT_ELF64 on x86 the x86 kernel could no longer be booted because too many kernel_args allocations were taking place and filling kernel_args_ranges. This was because for each image load it would check if the image is ELF64, fail and fall back to ELF32 (each ELF64 check allocated a preloaded_image). Changed elf_load_image() so that it only tries both when loading the kernel image, and then for modules it will only try the same ELF class as the kernel image. --- src/system/boot/loader/elf.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index f54e96b96d..1e1d7a4309 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -222,7 +222,7 @@ ELFLoader::Load(int fd, preloaded_image* _image) // inbetween. totalSize = secondRegion->start + secondRegion->size - firstRegion->start; if (totalSize > image->text_region.size + image->data_region.size - + 8 * 1024) { + + 0x200000) { status = B_BAD_DATA; goto error1; } @@ -543,22 +543,27 @@ elf_init() status_t elf_load_image(int fd, preloaded_image** _image) { - status_t status; + status_t status = B_ERROR; TRACE(("elf_load_image(fd = %d, _image = %p)\n", fd, _image)); #if BOOT_SUPPORT_ELF64 - status = ELF64Loader::Create(fd, _image); - if (status == B_OK) { - return ELF64Loader::Load(fd, *_image); - } else if (status == B_BAD_TYPE) { + if (gKernelArgs.kernel_image == NULL + || gKernelArgs.kernel_image->elf_class == ELFCLASS64) { + status = ELF64Loader::Create(fd, _image); + if (status == B_OK) + return ELF64Loader::Load(fd, *_image); + else if (status != B_BAD_TYPE) + return status; + } #endif + + if (gKernelArgs.kernel_image == NULL + || gKernelArgs.kernel_image->elf_class == ELFCLASS32) { status = ELF32Loader::Create(fd, _image); if (status == B_OK) return ELF32Loader::Load(fd, *_image); -#if BOOT_SUPPORT_ELF64 } -#endif return status; } From f6a3444449c452a63e0e0d91e8480f39bca81aed Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 19:22:33 +0100 Subject: [PATCH 036/273] Added x86_64 ELF64 relocation functions for the bootloader. All that's left to do now is handle the 64-bit load address properly. --- headers/private/kernel/elf_priv.h | 2 +- .../private/runtime_loader/runtime_loader.h | 2 +- src/system/boot/arch/x86/Jamfile | 1 + src/system/boot/arch/x86/arch_elf64.cpp | 1 + src/system/boot/arch/x86_64/Jamfile | 3 + src/system/boot/loader/Jamfile | 4 +- src/system/kernel/arch/x86/arch_elf.cpp | 1 - src/system/kernel/arch/x86_64/arch_elf.cpp | 86 +++++++++++++++++++ 8 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 src/system/boot/arch/x86/arch_elf64.cpp diff --git a/headers/private/kernel/elf_priv.h b/headers/private/kernel/elf_priv.h index 8169574606..fd386c49d4 100644 --- a/headers/private/kernel/elf_priv.h +++ b/headers/private/kernel/elf_priv.h @@ -69,7 +69,7 @@ struct elf_image_info { #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) -#define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num]) +#define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 132a674f5d..ddccda1209 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -154,7 +154,7 @@ typedef struct image_queue_t { #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) -#define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num]) +#define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index 21eb0ac506..e7cff1e494 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -19,6 +19,7 @@ local kernelLibArchObjects = ; BootMergeObject boot_arch_$(TARGET_ARCH).o : + arch_elf64.cpp $(kernelArchSources) $(kernelLibArchSources) : # additional flags diff --git a/src/system/boot/arch/x86/arch_elf64.cpp b/src/system/boot/arch/x86/arch_elf64.cpp new file mode 100644 index 0000000000..41e0198ea1 --- /dev/null +++ b/src/system/boot/arch/x86/arch_elf64.cpp @@ -0,0 +1 @@ +#include "../../../kernel/arch/x86_64/arch_elf.cpp" diff --git a/src/system/boot/arch/x86_64/Jamfile b/src/system/boot/arch/x86_64/Jamfile index dae289606e..3dd041891b 100644 --- a/src/system/boot/arch/x86_64/Jamfile +++ b/src/system/boot/arch/x86_64/Jamfile @@ -16,6 +16,7 @@ local librootOsArchSources = ; BootMergeObject boot_arch_$(TARGET_ARCH).o : + arch_elf64.cpp $(kernelArchSources) $(kernelLibArchSources) $(librootOsArchSources) @@ -28,3 +29,5 @@ SEARCH on [ FGristFiles $(kernelLibArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; SEARCH on [ FGristFiles $(librootOsArchSources) ] = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; +SEARCH on [ FGristFiles $(kernelArchSources) ] + = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index c9486992e9..f325c3279f 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -39,7 +39,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86_64\\\" - #BOOT_SUPPORT_ELF64 + BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI @@ -50,7 +50,7 @@ UsePrivateHeaders shared storage ; { defines += ALTERNATE_BOOT_ARCH=\\\"x86\\\" - #BOOT_SUPPORT_ELF64 + BOOT_SUPPORT_ELF64 BOOT_SUPPORT_PARTITION_EFI diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index df6cebe250..20570527d0 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -178,4 +178,3 @@ arch_elf_relocate_rela(struct elf_image_info *image, dprintf("arch_elf_relocate_rela: not supported on x86\n"); return B_ERROR; } - diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp index f8c6ad280e..b0cbe9d04a 100644 --- a/src/system/kernel/arch/x86_64/arch_elf.cpp +++ b/src/system/kernel/arch/x86_64/arch_elf.cpp @@ -3,10 +3,19 @@ * Distributed under the terms of the MIT License. */ +#ifdef _BOOT_MODE +# include +#endif + +#include #include +#include + +#include +#ifndef _BOOT_MODE // Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. status_t @@ -80,3 +89,80 @@ _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, { return B_ERROR; } +#endif + +#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rel(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) +//#endif +{ + dprintf("arch_elf_relocate_rel: not supported on x86_64\n"); + return B_ERROR; +} + + +//#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rela(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) +//#endif +{ + for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { + int type = ELF64_R_TYPE(rel[i].r_info); + int symIndex = ELF64_R_SYM(rel[i].r_info); + Elf64_Addr symAddr = 0; + + // Resolve the symbol, if any. + if (symIndex != 0) { + Elf64_Sym* symbol = SYMBOL(image, symIndex); + + status_t status; +//#ifdef _BOOT_MODE + status = boot_elf_resolve_symbol(image, symbol, &symAddr); +//#else +// status = elf_resolve_symbol(image, symbol, resolveImage, &S); +//#endif + if (status < B_OK) + return status; + } + + // Address of the relocation. + Elf64_Addr* resolveAddr = (Elf64_Addr *)(image->text_region.delta + + rel[i].r_offset); + + // Perform the relocation. + switch(type) { + case R_X86_64_NONE: + break; + case R_X86_64_64: + *resolveAddr = symAddr + rel[i].r_addend; + break; + case R_X86_64_PC32: + *resolveAddr = symAddr + rel[i].r_addend - rel[i].r_offset; + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *resolveAddr = symAddr + rel[i].r_addend; + break; + case R_X86_64_RELATIVE: + *resolveAddr = image->text_region.delta + rel[i].r_addend; + break; + default: + dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", + type); + return B_BAD_DATA; + } + } + + return B_OK; +} +#endif From 8846189866301c85683151a54ec88e809333ca7a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 24 Jun 2012 22:57:48 +0100 Subject: [PATCH 037/273] Handle 64-bit load addresses for ELF64 images in the bootloader. The ELF loader now uses a new platform function, platform_allocate_elf_region, which returns 2 addresses: the real load address and an address where the region is mapped in the loader's address space. All of the ELF loading code has been changed to access the load region through the mapped address rather than the addresses contained in the ELF image. The ELF64 version of platform_allocate_elf_region on x86 uses the existing MMU code, which maps everything at 0x80000000, but returns the correct 64-bit address. The long mode switch code will just set up the 64-bit address space with everything remapped at the correct address. --- headers/private/kernel/boot/elf.h | 22 ++++- headers/private/kernel/boot/platform.h | 7 ++ src/system/boot/arch/x86_64/Jamfile | 10 ++- src/system/boot/loader/elf.cpp | 81 +++++++++++++------ src/system/boot/platform/amiga_m68k/mmu.cpp | 14 ++++ src/system/boot/platform/atari_m68k/mmu.cpp | 14 ++++ src/system/boot/platform/bios_ia32/mmu.cpp | 37 +++++++++ src/system/boot/platform/cfe/mmu.cpp | 18 +++++ src/system/boot/platform/openfirmware/mmu.cpp | 18 +++++ .../boot/platform/raspberrypi_arm/mmu.cpp | 14 ++++ .../boot/platform/routerboard_mipsel/mmu.cpp | 9 +++ src/system/boot/platform/u-boot/mmu.cpp | 18 +++++ src/system/kernel/arch/x86_64/arch_elf.cpp | 21 +++-- 13 files changed, 243 insertions(+), 40 deletions(-) diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 88514d9c92..46bbfc1f56 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -1,7 +1,7 @@ /* * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the OpenBeOS License. + * Distributed under the terms of the MIT License. */ #ifndef KERNEL_BOOT_ELF_H #define KERNEL_BOOT_ELF_H @@ -44,9 +44,10 @@ struct preloaded_image { } _PACKED; struct preloaded_elf32_image : public preloaded_image { - Elf32_Ehdr elf_header; + Elf32_Ehdr elf_header; elf32_region text_region; elf32_region data_region; + uint32 mapped_delta; FixedWidthPointer syms; FixedWidthPointer rel; @@ -61,9 +62,10 @@ struct preloaded_elf32_image : public preloaded_image { } _PACKED; struct preloaded_elf64_image : public preloaded_image { - Elf64_Ehdr elf_header; + Elf64_Ehdr elf_header; elf64_region text_region; elf64_region data_region; + uint64 mapped_delta; FixedWidthPointer syms; FixedWidthPointer rel; @@ -77,11 +79,23 @@ struct preloaded_elf64_image : public preloaded_image { FixedWidthPointer debug_symbols; } _PACKED; - +#ifdef _BOOT_MODE extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress); extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress); +// Helper method to set a relocation at the mapped address in the loader's +// address space. +template +inline void +boot_elf_set_relocation(ImageType* image, AddrType resolveAddress, + AddrType finalAddress) +{ + AddrType* dest = (AddrType*)(addr_t)(resolveAddress + image->mapped_delta); + *dest = finalAddress; +} +#endif + #endif /* KERNEL_BOOT_ELF_H */ diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index 9f3c8eb637..c2514884fc 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -72,6 +72,13 @@ extern size_t platform_get_user_input_text(Menu *menu, MenuItem *item, char *buffer, size_t bufferSize); extern char* platform_debug_get_log_buffer(size_t* _size); +/* ELF functions */ + +extern status_t platform_allocate_elf_region(uint32 *_address, uint32 size, + uint8 protection, void **_mappedAddress); +extern status_t platform_allocate_elf_region(uint64 *_address, uint64 size, + uint8 protection, void **_mappedAddress); + #endif #endif /* KERNEL_BOOT_PLATFORM_H */ diff --git a/src/system/boot/arch/x86_64/Jamfile b/src/system/boot/arch/x86_64/Jamfile index 3dd041891b..f81c3f1b41 100644 --- a/src/system/boot/arch/x86_64/Jamfile +++ b/src/system/boot/arch/x86_64/Jamfile @@ -2,6 +2,10 @@ SubDir HAIKU_TOP src system boot arch x86_64 ; DEFINES += _BOOT_MODE ; +local bootArchSources = + arch_elf64.cpp +; + local kernelArchSources = arch_elf.cpp cpuid.S @@ -16,18 +20,18 @@ local librootOsArchSources = ; BootMergeObject boot_arch_$(TARGET_ARCH).o : - arch_elf64.cpp + $(bootArchSources) $(kernelArchSources) $(kernelLibArchSources) $(librootOsArchSources) : # additional flags ; +SEARCH on [ FGristFiles $(bootArchSources) ] + = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; SEARCH on [ FGristFiles $(kernelArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; SEARCH on [ FGristFiles $(kernelLibArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; SEARCH on [ FGristFiles $(librootOsArchSources) ] = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; -SEARCH on [ FGristFiles $(kernelArchSources) ] - = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 1e1d7a4309..cf780c3fca 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -38,6 +38,7 @@ class ELFLoader { private: typedef typename Class::ImageType ImageType; typedef typename Class::RegionType RegionType; + typedef typename Class::AddrType AddrType; typedef typename Class::EhdrType EhdrType; typedef typename Class::PhdrType PhdrType; typedef typename Class::ShdrType ShdrType; @@ -53,7 +54,7 @@ public: private: static status_t _LoadSymbolTable(int fd, ImageType* image); - static status_t _ParseDynamicSection(ImageType* image); + static status_t _ParseDynamicSection(ImageType* image, AddrType delta); }; @@ -62,6 +63,7 @@ struct ELF32Class { typedef preloaded_elf32_image ImageType; typedef elf32_region RegionType; + typedef Elf32_Addr AddrType; typedef Elf32_Ehdr EhdrType; typedef Elf32_Phdr PhdrType; typedef Elf32_Shdr ShdrType; @@ -80,6 +82,7 @@ struct ELF64Class { typedef preloaded_elf64_image ImageType; typedef elf64_region RegionType; + typedef Elf64_Addr AddrType; typedef Elf64_Ehdr EhdrType; typedef Elf64_Phdr PhdrType; typedef Elf64_Shdr ShdrType; @@ -132,6 +135,7 @@ ELFLoader::Load(int fd, preloaded_image* _image) size_t totalSize; ssize_t length; status_t status; + void* mappedRegion = NULL; ImageType* image = static_cast(_image); EhdrType& elfHeader = image->elf_header; @@ -196,8 +200,9 @@ ELFLoader::Load(int fd, preloaded_image* _image) B_PAGE_SIZE); region->delta = -region->start; - TRACE(("segment %ld: start = 0x%lx, size = %lu, delta = %lx\n", i, - region->start, region->size, region->delta)); + TRACE(("segment %ld: start = 0x%llx, size = %llu, delta = %llx\n", i, + (uint64)region->start, (uint64)region->size, + (int64)(AddrType)region->delta)); } // found both, text and data? @@ -228,10 +233,10 @@ ELFLoader::Load(int fd, preloaded_image* _image) } // The kernel and the modules are relocatable, thus - // platform_allocate_region() can automatically allocate an address, + // platform_allocate_elf_region() can automatically allocate an address, // but shall prefer the specified base address. - if (platform_allocate_region((void **)&firstRegion->start, totalSize, - B_READ_AREA | B_WRITE_AREA, false) < B_OK) { + if (platform_allocate_elf_region(&firstRegion->start, totalSize, + B_READ_AREA | B_WRITE_AREA, &mappedRegion) < B_OK) { status = B_NO_MEMORY; goto error1; } @@ -242,6 +247,16 @@ ELFLoader::Load(int fd, preloaded_image* _image) image->data_region.delta += image->data_region.start; image->text_region.delta += image->text_region.start; + TRACE(("text: start 0x%llx, size 0x%llx, delta 0x%llx\n", + (uint64)image->text_region.start, (uint64)image->text_region.size, + (int64)(AddrType)image->text_region.delta)); + TRACE(("data: start 0x%llx, size 0x%llx, delta 0x%llx\n", + (uint64)image->data_region.start, (uint64)image->data_region.size, + (int64)(AddrType)image->data_region.delta)); + + // Calculate the delta from a real load address to the mapped address + image->mapped_delta = (AddrType)(addr_t)mappedRegion - firstRegion->start; + // load program data for (int32 i = 0; i < elfHeader.e_phnum; i++) { @@ -258,10 +273,14 @@ ELFLoader::Load(int fd, preloaded_image* _image) else continue; - TRACE(("load segment %d (%ld bytes)...\n", i, header.p_filesz)); + // Calculate where to load the data to. + addr_t dest = region->start + image->mapped_delta; + + TRACE(("load segment %ld (%llu bytes) mapped at 0x%lx...\n", i, + (uint64)header.p_filesz, dest)); length = read_pos(fd, header.p_offset, - (void*)(region->start + (header.p_vaddr % B_PAGE_SIZE)), + (void*)(dest + (header.p_vaddr % B_PAGE_SIZE)), header.p_filesz); if (length < (ssize_t)header.p_filesz) { status = B_BAD_DATA; @@ -274,7 +293,7 @@ ELFLoader::Load(int fd, preloaded_image* _image) uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz; if (offset < region->size) - memset((void*)(region->start + offset), 0, region->size - offset); + memset((void*)(dest + offset), 0, region->size - offset); } // offset dynamic section, and program entry addresses by the delta of the @@ -294,8 +313,8 @@ ELFLoader::Load(int fd, preloaded_image* _image) return B_OK; error2: - if (image->text_region.start != 0) - platform_free_region((void*)image->text_region.start, totalSize); + if (mappedRegion != NULL) + platform_free_region(mappedRegion, totalSize); error1: free(programHeaders); kernel_args_free(image); @@ -310,13 +329,16 @@ ELFLoader::Relocate(preloaded_image* _image) { ImageType* image = static_cast(_image); - status_t status = _ParseDynamicSection(image); + // Pull information out of the dynamic section. First pass through we set + // the addresses we want in our address space. + status_t status = _ParseDynamicSection(image, image->mapped_delta); if (status != B_OK) return status; // deal with the rels first if (image->rel) { - TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(RelType))); + TRACE(("total %i relocs\n", + (int)image->rel_len / (int)sizeof(RelType))); status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); if (status < B_OK) @@ -324,15 +346,18 @@ ELFLoader::Relocate(preloaded_image* _image) } if (image->pltrel) { - TRACE(("total %i plt-relocs\n", - image->pltrel_len / (int)sizeof(RelType))); - RelType* pltrel = image->pltrel; if (image->pltrel_type == DT_REL) { + TRACE(("total %i plt-relocs\n", + (int)image->pltrel_len / (int)sizeof(RelType))); + status = boot_arch_elf_relocate_rel(image, pltrel, image->pltrel_len); } else { - status = boot_arch_elf_relocate_rela(image, (RelaType *)pltrel, + TRACE(("total %i plt-relocs\n", + (int)image->pltrel_len / (int)sizeof(RelaType))); + + status = boot_arch_elf_relocate_rela(image, (RelaType*)pltrel, image->pltrel_len); } if (status < B_OK) @@ -341,13 +366,17 @@ ELFLoader::Relocate(preloaded_image* _image) if (image->rela) { TRACE(("total %i rela relocs\n", - image->rela_len / (int)sizeof(RelaType))); + (int)image->rela_len / (int)sizeof(RelaType))); status = boot_arch_elf_relocate_rela(image, image->rela, image->rela_len); if (status < B_OK) return status; } + // Make a second pass through the dynamic section, storing the correct + // virtual addresses for the kernel. + _ParseDynamicSection(image, 0); + return B_OK; } @@ -458,7 +487,7 @@ error1: template /*static*/ status_t -ELFLoader::_ParseDynamicSection(ImageType* image) +ELFLoader::_ParseDynamicSection(ImageType* image, AddrType delta) { image->syms = 0; image->rel = 0; @@ -469,10 +498,12 @@ ELFLoader::_ParseDynamicSection(ImageType* image) image->pltrel_len = 0; image->pltrel_type = 0; - DynType* d = (DynType*)image->dynamic_section.start; - if (!d) + if(image->dynamic_section.start == 0) return B_ERROR; + DynType* d = (DynType*)(addr_t)(image->dynamic_section.start + + image->mapped_delta); + for (int i = 0; d[i].d_tag != DT_NULL; i++) { switch (d[i].d_tag) { case DT_HASH: @@ -480,25 +511,25 @@ ELFLoader::_ParseDynamicSection(ImageType* image) break; case DT_SYMTAB: image->syms = (SymType*)(d[i].d_un.d_ptr - + image->text_region.delta); + + image->text_region.delta + delta); break; case DT_REL: image->rel = (RelType*)(d[i].d_un.d_ptr - + image->text_region.delta); + + image->text_region.delta + delta); break; case DT_RELSZ: image->rel_len = d[i].d_un.d_val; break; case DT_RELA: image->rela = (RelaType*)(d[i].d_un.d_ptr - + image->text_region.delta); + + image->text_region.delta + delta); break; case DT_RELASZ: image->rela_len = d[i].d_un.d_val; break; case DT_JMPREL: image->pltrel = (RelType*)(d[i].d_un.d_ptr - + image->text_region.delta); + + image->text_region.delta + delta); break; case DT_PLTRELSZ: image->pltrel_len = d[i].d_un.d_val; diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp b/src/system/boot/platform/amiga_m68k/mmu.cpp index 03f56b9f4e..040c34afa0 100644 --- a/src/system/boot/platform/amiga_m68k/mmu.cpp +++ b/src/system/boot/platform/amiga_m68k/mmu.cpp @@ -662,6 +662,20 @@ platform_free_region(void *address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + void *address = mmu_allocate((void *)*_address, size); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + + void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp b/src/system/boot/platform/atari_m68k/mmu.cpp index 7132119fd2..77759cd244 100644 --- a/src/system/boot/platform/atari_m68k/mmu.cpp +++ b/src/system/boot/platform/atari_m68k/mmu.cpp @@ -666,6 +666,20 @@ platform_free_region(void *address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + void *address = mmu_allocate((void *)*_address, size); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + + void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index cfed3de612..344abf7c4c 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -769,6 +769,43 @@ platform_free_region(void *address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + void *address = mmu_allocate((void *)*_address, size); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + + +status_t +platform_allocate_elf_region(uint64 *_address, uint64 size, uint8 protection, + void **_mappedAddress) +{ + // The 64-bit kernel is loaded to 0xFFFFFFFF80000000. You'll notice that + // the low 32 bits of this address are the same as the 32-bit KERNEL_BASE + // (0x80000000). Therefore, the way this function is implemented is to use + // mmu_allocate() and then set the upper 32 bits to all 1s. The long mode + // switch code will remap everything to the correct addresses. + + void *address = mmu_allocate((void *)(addr_t)(*_address & 0xFFFFFFFF), size); + if (address == NULL) + return B_NO_MEMORY; + + // This is the address that the ELF loading code will access the mapping + // through. + *_mappedAddress = address; + + *_address = (uint64)(uint32)address | 0xFFFFFFFF00000000LL; + return B_OK; +} + + void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/cfe/mmu.cpp b/src/system/boot/platform/cfe/mmu.cpp index b9f3143c6f..e33ebe7323 100644 --- a/src/system/boot/platform/cfe/mmu.cpp +++ b/src/system/boot/platform/cfe/mmu.cpp @@ -34,3 +34,21 @@ platform_free_region(void *address, size_t size) return arch_mmu_free(address, size); } + +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + if (size == 0) + return B_BAD_VALUE; + + void *address = arch_mmu_allocate((void *)*_address, size, protection, + exactAddress); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + diff --git a/src/system/boot/platform/openfirmware/mmu.cpp b/src/system/boot/platform/openfirmware/mmu.cpp index b765e8dcb1..f284dae029 100644 --- a/src/system/boot/platform/openfirmware/mmu.cpp +++ b/src/system/boot/platform/openfirmware/mmu.cpp @@ -34,3 +34,21 @@ platform_free_region(void *address, size_t size) return arch_mmu_free(address, size); } + +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + if (size == 0) + return B_BAD_VALUE; + + void *address = arch_mmu_allocate((void *)*_address, size, protection, + exactAddress); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.cpp b/src/system/boot/platform/raspberrypi_arm/mmu.cpp index 18c39f5a39..3b52275e53 100644 --- a/src/system/boot/platform/raspberrypi_arm/mmu.cpp +++ b/src/system/boot/platform/raspberrypi_arm/mmu.cpp @@ -678,6 +678,20 @@ platform_free_region(void *address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ + void *address = mmu_allocate((void *)*_address, size); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +} + + void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/routerboard_mipsel/mmu.cpp b/src/system/boot/platform/routerboard_mipsel/mmu.cpp index cb4611926d..744cac4a3a 100644 --- a/src/system/boot/platform/routerboard_mipsel/mmu.cpp +++ b/src/system/boot/platform/routerboard_mipsel/mmu.cpp @@ -79,6 +79,15 @@ platform_free_region(void* address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ +#warning IMPLEMENT platform_allocate_elf_region + return B_ERROR; +} + + void platform_release_heap(struct stage2_args* args, void* base) { diff --git a/src/system/boot/platform/u-boot/mmu.cpp b/src/system/boot/platform/u-boot/mmu.cpp index e38d931171..a1d001c714 100644 --- a/src/system/boot/platform/u-boot/mmu.cpp +++ b/src/system/boot/platform/u-boot/mmu.cpp @@ -681,6 +681,24 @@ platform_free_region(void *address, size_t size) } +status_t +platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, + void **_mappedAddress) +{ +#ifdef __ARM__ + void *address = mmu_allocate((void *)*_address, size); + if (address == NULL) + return B_NO_MEMORY; + + *_address = (uint32)address; + *_mappedAddress = address; + return B_OK; +#else + return B_ERROR; +#endif +} + + void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp index b0cbe9d04a..09d2f341e2 100644 --- a/src/system/kernel/arch/x86_64/arch_elf.cpp +++ b/src/system/kernel/arch/x86_64/arch_elf.cpp @@ -136,31 +136,36 @@ boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, } // Address of the relocation. - Elf64_Addr* resolveAddr = (Elf64_Addr *)(image->text_region.delta - + rel[i].r_offset); + Elf64_Addr relocAddr = image->text_region.delta + rel[i].r_offset; - // Perform the relocation. + // Calculate the relocation value. + Elf64_Addr relocValue; switch(type) { case R_X86_64_NONE: - break; + continue; case R_X86_64_64: - *resolveAddr = symAddr + rel[i].r_addend; + relocValue = symAddr + rel[i].r_addend; break; case R_X86_64_PC32: - *resolveAddr = symAddr + rel[i].r_addend - rel[i].r_offset; + relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; break; case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: - *resolveAddr = symAddr + rel[i].r_addend; + relocValue = symAddr + rel[i].r_addend; break; case R_X86_64_RELATIVE: - *resolveAddr = image->text_region.delta + rel[i].r_addend; + relocValue = image->text_region.delta + rel[i].r_addend; break; default: dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", type); return B_BAD_DATA; } +#ifdef _BOOT_MODE + boot_elf_set_relocation(image, relocAddr, relocValue); +#else + *(Elf64_Addr *)relocAddr = relocValue; +#endif } return B_OK; From 6f6d78e877c1a485d98de60395854a6d6de61c0d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 25 Jun 2012 13:00:50 +0100 Subject: [PATCH 038/273] Cleaned up ELF64 address handling. * platform_allocate_elf_region() is removed, it is implemented in platform- independent code now (ELF*Class::AllocateRegion). For ELF64 it is now assumed that 64-bit addresses are mapped in the loader's 32-bit address space as (address - KERNEL_BASE_64BIT + KERNEL_BASE). * mapped_delta field from preloaded_*_image removed, now handled compile-time using the ELF*Class::Map method. * Also link the kernel with -z max-page-size=0x1000, removes the need for 2MB alignment on the data segment (not going to map the kernel with large pages for the time being). --- build/jam/BuildSetup | 1 + headers/private/kernel/arch/x86/arch_kernel.h | 4 + .../private/kernel/arch/x86_64/arch_kernel.h | 29 ++-- headers/private/kernel/boot/elf.h | 16 +- headers/private/kernel/boot/platform.h | 7 - src/system/boot/loader/elf.cpp | 160 +++++++++++------- src/system/boot/platform/amiga_m68k/mmu.cpp | 14 -- src/system/boot/platform/atari_m68k/mmu.cpp | 14 -- src/system/boot/platform/bios_ia32/mmu.cpp | 37 ---- src/system/boot/platform/cfe/mmu.cpp | 18 -- src/system/boot/platform/openfirmware/mmu.cpp | 18 -- .../boot/platform/raspberrypi_arm/mmu.cpp | 14 -- .../boot/platform/routerboard_mipsel/mmu.cpp | 9 - src/system/boot/platform/u-boot/mmu.cpp | 18 -- src/system/kernel/arch/x86_64/arch_elf.cpp | 2 +- src/system/ldscripts/x86_64/kernel.ld | 2 +- 16 files changed, 124 insertions(+), 239 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 690227cb67..97856a8aec 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -388,6 +388,7 @@ switch $(HAIKU_ARCH) { # code due to interrupts. HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel -mno-red-zone ; HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel -mno-red-zone ; + HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ; # Bootloader is 32-bit. HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 66bbfd0dbc..418d707c47 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -17,6 +17,10 @@ #define KERNEL_SIZE 0x80000000 #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) +#ifdef _BOOT_MODE +# define KERNEL_BASE_64BIT 0xffffffff80000000 +#endif + /* User space layout is a little special: * The user space does not completely cover the space not covered by the * kernel. There is a gap of 64kb between the user and kernel space. The 64kb diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h index 056efafcfa..612f0adff8 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel.h @@ -13,29 +13,30 @@ // Base of the kernel address space. // When compiling the bootloader, KERNEL_BASE is set to the x86 base address, -// the correct 64-bit addresses are calculated differently. -// For the kernel, this is the base of the kernel address space. This is NOT -// the address where the kernel is loaded to: the kernel is loaded in the top -// 2GB of the virtual address space as required by GCC's kernel code model. +// KERNEL_BASE_64BIT is set to where the kernel loaded to. +// For the kernel, KERNEL_BASE is the base of the kernel address space. This is +// NOT the address where the kernel is loaded to: the kernel is loaded in the +// top 2GB of the virtual address space as required by GCC's kernel code model. // The whole kernel address space is the top 512GB of the address space. #ifdef _BOOT_MODE -# define KERNEL_BASE 0x80000000 +# define KERNEL_BASE 0x80000000 +# define KERNEL_BASE_64BIT 0xffffffff80000000 #else -# define KERNEL_BASE 0xFFFFFF8000000000 +# define KERNEL_BASE 0xffffff8000000000 #endif -#define KERNEL_SIZE 0x8000000000 -#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) +#define KERNEL_SIZE 0x8000000000 +#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) // Userspace address space layout. -#define USER_BASE 0x0 -#define USER_BASE_ANY 0x100000 -#define USER_SIZE 0x800000000000 -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_BASE 0x0 +#define USER_BASE_ANY 0x100000 +#define USER_SIZE 0x800000000000 +#define USER_TOP (USER_BASE + USER_SIZE) -#define KERNEL_USER_DATA_BASE 0x7FFFEFFF0000 -#define USER_STACK_REGION 0x7FFFF0000000 +#define KERNEL_USER_DATA_BASE 0x7fffefff0000 +#define USER_STACK_REGION 0x7ffff0000000 #define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index 46bbfc1f56..d2cfe06195 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -47,7 +47,6 @@ struct preloaded_elf32_image : public preloaded_image { Elf32_Ehdr elf_header; elf32_region text_region; elf32_region data_region; - uint32 mapped_delta; FixedWidthPointer syms; FixedWidthPointer rel; @@ -65,7 +64,6 @@ struct preloaded_elf64_image : public preloaded_image { Elf64_Ehdr elf_header; elf64_region text_region; elf64_region data_region; - uint64 mapped_delta; FixedWidthPointer syms; FixedWidthPointer rel; @@ -84,18 +82,8 @@ extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress); extern status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress); - - -// Helper method to set a relocation at the mapped address in the loader's -// address space. -template -inline void -boot_elf_set_relocation(ImageType* image, AddrType resolveAddress, - AddrType finalAddress) -{ - AddrType* dest = (AddrType*)(addr_t)(resolveAddress + image->mapped_delta); - *dest = finalAddress; -} +extern void boot_elf64_set_relocation(Elf64_Addr resolveAddress, + Elf64_Addr finalAddress); #endif #endif /* KERNEL_BOOT_ELF_H */ diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index c2514884fc..9f3c8eb637 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -72,13 +72,6 @@ extern size_t platform_get_user_input_text(Menu *menu, MenuItem *item, char *buffer, size_t bufferSize); extern char* platform_debug_get_log_buffer(size_t* _size); -/* ELF functions */ - -extern status_t platform_allocate_elf_region(uint32 *_address, uint32 size, - uint8 protection, void **_mappedAddress); -extern status_t platform_allocate_elf_region(uint64 *_address, uint64 size, - uint8 protection, void **_mappedAddress); - #endif #endif /* KERNEL_BOOT_PLATFORM_H */ diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index cf780c3fca..84a1d0a3d9 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -51,10 +51,12 @@ public: static status_t Create(int fd, preloaded_image** _image); static status_t Load(int fd, preloaded_image* image); static status_t Relocate(preloaded_image* image); + static status_t Resolve(ImageType* image, SymType* symbol, + AddrType* symbolAddress); private: static status_t _LoadSymbolTable(int fd, ImageType* image); - static status_t _ParseDynamicSection(ImageType* image, AddrType delta); + static status_t _ParseDynamicSection(ImageType* image); }; @@ -71,6 +73,25 @@ struct ELF32Class { typedef Elf32_Sym SymType; typedef Elf32_Rel RelType; typedef Elf32_Rela RelaType; + + static inline status_t + AllocateRegion(AddrType* _address, AddrType size, uint8 protection, + void **_mappedAddress) + { + status_t status = platform_allocate_region((void**)_address, size, + protection, false); + if (status < B_OK) + return status; + + *_mappedAddress = (void*)*_address; + return B_OK; + } + + static inline void* + Map(AddrType address) + { + return (void*)address; + } }; typedef ELFLoader ELF32Loader; @@ -90,6 +111,31 @@ struct ELF64Class { typedef Elf64_Sym SymType; typedef Elf64_Rel RelType; typedef Elf64_Rela RelaType; + + static inline status_t + AllocateRegion(AddrType* _address, AddrType size, uint8 protection, + void **_mappedAddress) + { + // Assume the real 64-bit base address is KERNEL_BASE_64BIT and the + // mappings in the loader address space are at KERNEL_BASE. + + void* address = (void*)(addr_t)(*_address & 0xffffffff); + + status_t status = platform_allocate_region(&address, size, protection, + false); + if (status < B_OK) + return status; + + *_mappedAddress = address; + *_address = (AddrType)(addr_t)address + KERNEL_BASE_64BIT - KERNEL_BASE; + return B_OK; + } + + static inline void* + Map(AddrType address) + { + return (void*)(addr_t)(address - KERNEL_BASE_64BIT + KERNEL_BASE); + } }; typedef ELFLoader ELF64Loader; @@ -227,15 +273,15 @@ ELFLoader::Load(int fd, preloaded_image* _image) // inbetween. totalSize = secondRegion->start + secondRegion->size - firstRegion->start; if (totalSize > image->text_region.size + image->data_region.size - + 0x200000) { + + 8 * 1024) { status = B_BAD_DATA; goto error1; } - // The kernel and the modules are relocatable, thus - // platform_allocate_elf_region() can automatically allocate an address, - // but shall prefer the specified base address. - if (platform_allocate_elf_region(&firstRegion->start, totalSize, + // The kernel and the modules are relocatable, thus AllocateRegion() + // can automatically allocate an address, but shall prefer the specified + // base address. + if (Class::AllocateRegion(&firstRegion->start, totalSize, B_READ_AREA | B_WRITE_AREA, &mappedRegion) < B_OK) { status = B_NO_MEMORY; goto error1; @@ -254,9 +300,6 @@ ELFLoader::Load(int fd, preloaded_image* _image) (uint64)image->data_region.start, (uint64)image->data_region.size, (int64)(AddrType)image->data_region.delta)); - // Calculate the delta from a real load address to the mapped address - image->mapped_delta = (AddrType)(addr_t)mappedRegion - firstRegion->start; - // load program data for (int32 i = 0; i < elfHeader.e_phnum; i++) { @@ -273,14 +316,11 @@ ELFLoader::Load(int fd, preloaded_image* _image) else continue; - // Calculate where to load the data to. - addr_t dest = region->start + image->mapped_delta; - - TRACE(("load segment %ld (%llu bytes) mapped at 0x%lx...\n", i, - (uint64)header.p_filesz, dest)); + TRACE(("load segment %ld (%llu bytes) mapped at %p...\n", i, + (uint64)header.p_filesz, Class::Map(region->start))); length = read_pos(fd, header.p_offset, - (void*)(dest + (header.p_vaddr % B_PAGE_SIZE)), + Class::Map(region->start + (header.p_vaddr % B_PAGE_SIZE)), header.p_filesz); if (length < (ssize_t)header.p_filesz) { status = B_BAD_DATA; @@ -293,7 +333,7 @@ ELFLoader::Load(int fd, preloaded_image* _image) uint32 offset = (header.p_vaddr % B_PAGE_SIZE) + header.p_filesz; if (offset < region->size) - memset((void*)(dest + offset), 0, region->size - offset); + memset(Class::Map(region->start + offset), 0, region->size - offset); } // offset dynamic section, and program entry addresses by the delta of the @@ -329,9 +369,7 @@ ELFLoader::Relocate(preloaded_image* _image) { ImageType* image = static_cast(_image); - // Pull information out of the dynamic section. First pass through we set - // the addresses we want in our address space. - status_t status = _ParseDynamicSection(image, image->mapped_delta); + status_t status = _ParseDynamicSection(image); if (status != B_OK) return status; @@ -373,13 +411,33 @@ ELFLoader::Relocate(preloaded_image* _image) return status; } - // Make a second pass through the dynamic section, storing the correct - // virtual addresses for the kernel. - _ParseDynamicSection(image, 0); - return B_OK; } +template +/*static*/ status_t +ELFLoader::Resolve(ImageType* image, SymType* symbol, + AddrType* symbolAddress) +{ + switch (symbol->st_shndx) { + case SHN_UNDEF: + // Since we do that only for the kernel, there shouldn't be + // undefined symbols. + return B_MISSING_SYMBOL; + case SHN_ABS: + *symbolAddress = symbol->st_value; + return B_NO_ERROR; + case SHN_COMMON: + // ToDo: finish this + TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n")); + return B_ERROR; + default: + // standard symbol + *symbolAddress = symbol->st_value + image->text_region.delta; + return B_OK; + } +} + template /*static*/ status_t @@ -487,7 +545,7 @@ error1: template /*static*/ status_t -ELFLoader::_ParseDynamicSection(ImageType* image, AddrType delta) +ELFLoader::_ParseDynamicSection(ImageType* image) { image->syms = 0; image->rel = 0; @@ -501,8 +559,7 @@ ELFLoader::_ParseDynamicSection(ImageType* image, AddrType delta) if(image->dynamic_section.start == 0) return B_ERROR; - DynType* d = (DynType*)(addr_t)(image->dynamic_section.start - + image->mapped_delta); + DynType* d = (DynType*)Class::Map(image->dynamic_section.start); for (int i = 0; d[i].d_tag != DT_NULL; i++) { switch (d[i].d_tag) { @@ -510,26 +567,26 @@ ELFLoader::_ParseDynamicSection(ImageType* image, AddrType delta) case DT_STRTAB: break; case DT_SYMTAB: - image->syms = (SymType*)(d[i].d_un.d_ptr - + image->text_region.delta + delta); + image->syms = (SymType*)Class::Map(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_REL: - image->rel = (RelType*)(d[i].d_un.d_ptr - + image->text_region.delta + delta); + image->rel = (RelType*)Class::Map(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_RELSZ: image->rel_len = d[i].d_un.d_val; break; case DT_RELA: - image->rela = (RelaType*)(d[i].d_un.d_ptr - + image->text_region.delta + delta); + image->rela = (RelaType*)Class::Map(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_RELASZ: image->rela_len = d[i].d_un.d_val; break; case DT_JMPREL: - image->pltrel = (RelType*)(d[i].d_un.d_ptr - + image->text_region.delta + delta); + image->pltrel = (RelType*)Class::Map(d[i].d_un.d_ptr + + image->text_region.delta); break; case DT_PLTRELSZ: image->pltrel_len = d[i].d_un.d_val; @@ -656,35 +713,11 @@ elf_relocate_image(preloaded_image* image) } -template -inline status_t -resolve_symbol(ImageType* image, SymType* symbol, AddrType* symbolAddress) -{ - switch (symbol->st_shndx) { - case SHN_UNDEF: - // Since we do that only for the kernel, there shouldn't be - // undefined symbols. - return B_MISSING_SYMBOL; - case SHN_ABS: - *symbolAddress = symbol->st_value; - return B_NO_ERROR; - case SHN_COMMON: - // ToDo: finish this - TRACE(("elf_resolve_symbol: COMMON symbol, finish me!\n")); - return B_ERROR; - default: - // standard symbol - *symbolAddress = symbol->st_value + image->text_region.delta; - return B_NO_ERROR; - } -} - - status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress) { - return resolve_symbol(image, symbol, symbolAddress); + return ELF32Loader::Resolve(image, symbol, symbolAddress); } @@ -693,6 +726,13 @@ status_t boot_elf_resolve_symbol(preloaded_elf64_image* image, struct Elf64_Sym* symbol, Elf64_Addr* symbolAddress) { - return resolve_symbol(image, symbol, symbolAddress); + return ELF64Loader::Resolve(image, symbol, symbolAddress); +} + +void +boot_elf64_set_relocation(Elf64_Addr resolveAddress, Elf64_Addr finalAddress) +{ + Elf64_Addr* dest = (Elf64_Addr*)ELF64Class::Map(resolveAddress); + *dest = finalAddress; } #endif diff --git a/src/system/boot/platform/amiga_m68k/mmu.cpp b/src/system/boot/platform/amiga_m68k/mmu.cpp index 040c34afa0..03f56b9f4e 100644 --- a/src/system/boot/platform/amiga_m68k/mmu.cpp +++ b/src/system/boot/platform/amiga_m68k/mmu.cpp @@ -662,20 +662,6 @@ platform_free_region(void *address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - void *address = mmu_allocate((void *)*_address, size); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - - void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/atari_m68k/mmu.cpp b/src/system/boot/platform/atari_m68k/mmu.cpp index 77759cd244..7132119fd2 100644 --- a/src/system/boot/platform/atari_m68k/mmu.cpp +++ b/src/system/boot/platform/atari_m68k/mmu.cpp @@ -666,20 +666,6 @@ platform_free_region(void *address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - void *address = mmu_allocate((void *)*_address, size); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - - void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 344abf7c4c..cfed3de612 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -769,43 +769,6 @@ platform_free_region(void *address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - void *address = mmu_allocate((void *)*_address, size); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - - -status_t -platform_allocate_elf_region(uint64 *_address, uint64 size, uint8 protection, - void **_mappedAddress) -{ - // The 64-bit kernel is loaded to 0xFFFFFFFF80000000. You'll notice that - // the low 32 bits of this address are the same as the 32-bit KERNEL_BASE - // (0x80000000). Therefore, the way this function is implemented is to use - // mmu_allocate() and then set the upper 32 bits to all 1s. The long mode - // switch code will remap everything to the correct addresses. - - void *address = mmu_allocate((void *)(addr_t)(*_address & 0xFFFFFFFF), size); - if (address == NULL) - return B_NO_MEMORY; - - // This is the address that the ELF loading code will access the mapping - // through. - *_mappedAddress = address; - - *_address = (uint64)(uint32)address | 0xFFFFFFFF00000000LL; - return B_OK; -} - - void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/cfe/mmu.cpp b/src/system/boot/platform/cfe/mmu.cpp index e33ebe7323..b9f3143c6f 100644 --- a/src/system/boot/platform/cfe/mmu.cpp +++ b/src/system/boot/platform/cfe/mmu.cpp @@ -34,21 +34,3 @@ platform_free_region(void *address, size_t size) return arch_mmu_free(address, size); } - -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - if (size == 0) - return B_BAD_VALUE; - - void *address = arch_mmu_allocate((void *)*_address, size, protection, - exactAddress); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - diff --git a/src/system/boot/platform/openfirmware/mmu.cpp b/src/system/boot/platform/openfirmware/mmu.cpp index f284dae029..b765e8dcb1 100644 --- a/src/system/boot/platform/openfirmware/mmu.cpp +++ b/src/system/boot/platform/openfirmware/mmu.cpp @@ -34,21 +34,3 @@ platform_free_region(void *address, size_t size) return arch_mmu_free(address, size); } - -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - if (size == 0) - return B_BAD_VALUE; - - void *address = arch_mmu_allocate((void *)*_address, size, protection, - exactAddress); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - diff --git a/src/system/boot/platform/raspberrypi_arm/mmu.cpp b/src/system/boot/platform/raspberrypi_arm/mmu.cpp index 3b52275e53..18c39f5a39 100644 --- a/src/system/boot/platform/raspberrypi_arm/mmu.cpp +++ b/src/system/boot/platform/raspberrypi_arm/mmu.cpp @@ -678,20 +678,6 @@ platform_free_region(void *address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ - void *address = mmu_allocate((void *)*_address, size); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -} - - void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/boot/platform/routerboard_mipsel/mmu.cpp b/src/system/boot/platform/routerboard_mipsel/mmu.cpp index 744cac4a3a..cb4611926d 100644 --- a/src/system/boot/platform/routerboard_mipsel/mmu.cpp +++ b/src/system/boot/platform/routerboard_mipsel/mmu.cpp @@ -79,15 +79,6 @@ platform_free_region(void* address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ -#warning IMPLEMENT platform_allocate_elf_region - return B_ERROR; -} - - void platform_release_heap(struct stage2_args* args, void* base) { diff --git a/src/system/boot/platform/u-boot/mmu.cpp b/src/system/boot/platform/u-boot/mmu.cpp index a1d001c714..e38d931171 100644 --- a/src/system/boot/platform/u-boot/mmu.cpp +++ b/src/system/boot/platform/u-boot/mmu.cpp @@ -681,24 +681,6 @@ platform_free_region(void *address, size_t size) } -status_t -platform_allocate_elf_region(uint32 *_address, uint32 size, uint8 protection, - void **_mappedAddress) -{ -#ifdef __ARM__ - void *address = mmu_allocate((void *)*_address, size); - if (address == NULL) - return B_NO_MEMORY; - - *_address = (uint32)address; - *_mappedAddress = address; - return B_OK; -#else - return B_ERROR; -#endif -} - - void platform_release_heap(struct stage2_args *args, void *base) { diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp index 09d2f341e2..30f022d7db 100644 --- a/src/system/kernel/arch/x86_64/arch_elf.cpp +++ b/src/system/kernel/arch/x86_64/arch_elf.cpp @@ -162,7 +162,7 @@ boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, return B_BAD_DATA; } #ifdef _BOOT_MODE - boot_elf_set_relocation(image, relocAddr, relocValue); + boot_elf64_set_relocation(relocAddr, relocValue); #else *(Elf64_Addr *)relocAddr = relocValue; #endif diff --git a/src/system/ldscripts/x86_64/kernel.ld b/src/system/ldscripts/x86_64/kernel.ld index 1496cc7cae..5b454248db 100644 --- a/src/system/ldscripts/x86_64/kernel.ld +++ b/src/system/ldscripts/x86_64/kernel.ld @@ -29,7 +29,7 @@ SECTIONS .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } /* writable data */ - . = ALIGN (0x200000); + . = ALIGN (0x1000); __data_start = .; .data : { *(.data .data.* .gnu.linkonce.d.*) } From f69dd487b1c4e0a3f35d6477e9a6720315e89f35 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 25 Jun 2012 13:28:28 +0100 Subject: [PATCH 039/273] Fixed x86 GCC2 build. --- headers/private/kernel/arch/x86/arch_kernel.h | 2 +- headers/private/kernel/arch/x86_64/arch_kernel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 418d707c47..00e2ea868d 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -18,7 +18,7 @@ #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) #ifdef _BOOT_MODE -# define KERNEL_BASE_64BIT 0xffffffff80000000 +# define KERNEL_BASE_64BIT 0xffffffff80000000ll #endif /* User space layout is a little special: diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h index 612f0adff8..e19b5c25b8 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel.h @@ -20,7 +20,7 @@ // The whole kernel address space is the top 512GB of the address space. #ifdef _BOOT_MODE # define KERNEL_BASE 0x80000000 -# define KERNEL_BASE_64BIT 0xffffffff80000000 +# define KERNEL_BASE_64BIT 0xffffffff80000000ll #else # define KERNEL_BASE 0xffffff8000000000 #endif From 5a17b2f1b272c71940a67474fc029fa5cf40cff6 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 26 Jun 2012 10:54:37 +0100 Subject: [PATCH 040/273] Forgot to change driver_settings_file to use FixedWidthPointer. --- headers/private/kernel/boot/driver_settings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/headers/private/kernel/boot/driver_settings.h b/headers/private/kernel/boot/driver_settings.h index bee57df92e..03d0d03b79 100644 --- a/headers/private/kernel/boot/driver_settings.h +++ b/headers/private/kernel/boot/driver_settings.h @@ -13,8 +13,8 @@ struct driver_settings_file { FixedWidthPointer next; char name[B_OS_NAME_LENGTH]; - char *buffer; - size_t size; -}; + FixedWidthPointer buffer; + uint32 size; +} _PACKED; #endif /* KERNEL_BOOT_DRIVER_SETTINGS_H */ From a820f12943d570cfcb6dbb78781dc587f56e0da8 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 26 Jun 2012 10:59:03 +0100 Subject: [PATCH 041/273] Style fixes to elf.cpp. --- src/system/boot/loader/elf.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 84a1d0a3d9..8494ff7f6d 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -76,11 +76,11 @@ struct ELF32Class { static inline status_t AllocateRegion(AddrType* _address, AddrType size, uint8 protection, - void **_mappedAddress) + void** _mappedAddress) { status_t status = platform_allocate_region((void**)_address, size, protection, false); - if (status < B_OK) + if (status != B_OK) return status; *_mappedAddress = (void*)*_address; @@ -123,7 +123,7 @@ struct ELF64Class { status_t status = platform_allocate_region(&address, size, protection, false); - if (status < B_OK) + if (status != B_OK) return status; *_mappedAddress = address; @@ -282,7 +282,7 @@ ELFLoader::Load(int fd, preloaded_image* _image) // can automatically allocate an address, but shall prefer the specified // base address. if (Class::AllocateRegion(&firstRegion->start, totalSize, - B_READ_AREA | B_WRITE_AREA, &mappedRegion) < B_OK) { + B_READ_AREA | B_WRITE_AREA, &mappedRegion) != B_OK) { status = B_NO_MEMORY; goto error1; } @@ -379,7 +379,7 @@ ELFLoader::Relocate(preloaded_image* _image) (int)image->rel_len / (int)sizeof(RelType))); status = boot_arch_elf_relocate_rel(image, image->rel, image->rel_len); - if (status < B_OK) + if (status != B_OK) return status; } @@ -398,7 +398,7 @@ ELFLoader::Relocate(preloaded_image* _image) status = boot_arch_elf_relocate_rela(image, (RelaType*)pltrel, image->pltrel_len); } - if (status < B_OK) + if (status != B_OK) return status; } @@ -407,7 +407,7 @@ ELFLoader::Relocate(preloaded_image* _image) (int)image->rela_len / (int)sizeof(RelaType))); status = boot_arch_elf_relocate_rela(image, image->rela, image->rela_len); - if (status < B_OK) + if (status != B_OK) return status; } From e5fc2bfcab8c15a3ff7d33c358f9aa82ed73c823 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 26 Jun 2012 11:01:23 +0100 Subject: [PATCH 042/273] Implemented long mode setup/switch code, the bootloader can now start the 64-bit kernel! The setup procedure is fairly simple: create a 64-bit GDT and 64-bit page tables that include all kernel mappings from the 32-bit address space, but at the correct 64-bit address, then go through kernel_args and changes all virtual addresses to 64-bit addresses, and finally switch to long mode and jump to the kernel. --- .../kernel/arch/x86/arch_kernel_args.h | 10 +- .../private/kernel/arch/x86_64/descriptors.h | 149 +++++++++ src/system/boot/platform/bios_ia32/Jamfile | 2 + src/system/boot/platform/bios_ia32/long.cpp | 290 ++++++++++++++++++ src/system/boot/platform/bios_ia32/long.h | 18 ++ src/system/boot/platform/bios_ia32/long_asm.S | 75 +++++ src/system/boot/platform/bios_ia32/mmu.cpp | 55 +++- src/system/boot/platform/bios_ia32/mmu.h | 6 + src/system/boot/platform/bios_ia32/smp.cpp | 2 +- src/system/boot/platform/bios_ia32/start.cpp | 7 + src/system/boot/platform/pxe_ia32/Jamfile | 2 + src/system/kernel/arch/x86/arch_cpu.cpp | 2 +- src/system/kernel/arch/x86/arch_int.cpp | 2 +- .../x86/paging/32bit/X86PagingMethod32Bit.cpp | 4 +- .../x86/paging/pae/X86PagingMethodPAE.cpp | 3 +- src/system/kernel/main.cpp | 2 + 16 files changed, 614 insertions(+), 15 deletions(-) create mode 100644 headers/private/kernel/arch/x86_64/descriptors.h create mode 100644 src/system/boot/platform/bios_ia32/long.cpp create mode 100644 src/system/boot/platform/bios_ia32/long.h create mode 100644 src/system/boot/platform/bios_ia32/long_asm.S diff --git a/headers/private/kernel/arch/x86/arch_kernel_args.h b/headers/private/kernel/arch/x86/arch_kernel_args.h index de17c7ced6..7e6c967582 100644 --- a/headers/private/kernel/arch/x86/arch_kernel_args.h +++ b/headers/private/kernel/arch/x86/arch_kernel_args.h @@ -26,15 +26,15 @@ typedef struct { uint32 system_time_cv_factor; uint64 cpu_clock_speed; uint32 phys_pgdir; - uint32 vir_pgdir; + uint64 vir_pgdir; uint32 num_pgtables; uint32 pgtables[MAX_BOOT_PTABLES]; - uint32 virtual_end; + uint64 virtual_end; uint32 phys_idt; - uint32 vir_idt; + uint64 vir_idt; uint32 phys_gdt; - uint32 vir_gdt; - uint32 page_hole; + uint64 vir_gdt; + uint64 page_hole; // smp stuff uint32 apic_time_cv_factor; // apic ticks per second uint32 apic_phys; diff --git a/headers/private/kernel/arch/x86_64/descriptors.h b/headers/private/kernel/arch/x86_64/descriptors.h new file mode 100644 index 0000000000..a1850f0dd1 --- /dev/null +++ b/headers/private/kernel/arch/x86_64/descriptors.h @@ -0,0 +1,149 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H +#define _KERNEL_ARCH_X86_64_DESCRIPTORS_H + + +// Segment definitions. +// Note that the ordering of these is important to SYSCALL/SYSRET. +#define KERNEL_CODE_SEG 0x08 +#define KERNEL_DATA_SEG 0x10 +#define USER_DATA_SEG 0x18 +#define USER_CODE_SEG 0x20 + + +#ifndef _ASSEMBLER + + +#define TSS_BASE_SEGMENT 5 +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) + + +// Structure of a segment descriptor. +struct segment_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 long_mode : 1; + uint32 d_b : 1; + uint32 granularity : 1; + uint32 base1 : 8; +} _PACKED; + +// Structure of a TSS segment descriptor. +struct tss_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 unused1 : 2; + uint32 granularity : 1; + uint32 base1 : 8; + uint32 base2 : 32; + uint32 unused2 : 32; +} _PACKED; + +// Structure of an interrupt descriptor. +struct interrupt_descriptor { + uint32 base0 : 16; + uint32 sel : 16; + uint32 ist : 3; + uint32 unused : 5; + uint32 flags : 8; + uint32 base1 : 16; + uint32 base2 : 32; + uint32 reserved : 32; +} _PACKED; + +enum descriptor_privilege_levels { + DPL_KERNEL = 0, + DPL_USER = 3, +}; + +enum descriptor_types { + // Code/data descriptor types. + DT_CODE_EXECUTE_ONLY = 0x8, + DT_CODE_ACCESSED = 0x9, + DT_CODE_READABLE = 0xa, + DT_CODE_CONFORM = 0xc, + DT_DATA_READ_ONLY = 0x0, + DT_DATA_ACCESSED = 0x1, + DT_DATA_WRITEABLE = 0x2, + DT_DATA_EXPANSION_DOWN = 0x4, + + // System descriptor types. + DT_TSS = 9, + + // Descriptor types + DT_SYSTEM_SEGMENT = 0, + DT_CODE_DATA_SEGMENT = 1, +}; + + +static inline void +clear_segment_descriptor(segment_descriptor* desc) +{ + *(uint64*)desc = 0; +} + + +static inline void +set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) +{ + clear_segment_descriptor(desc); + + // In 64-bit mode the CPU ignores the base/limit of code/data segments, + // it always treats base as 0 and does no limit checks. + desc->base0 = 0; + desc->base1 = 0; + desc->limit0 = 0xFFFF; + desc->limit1 = 0xF; + desc->granularity = 1; + + desc->type = type; + desc->desc_type = DT_CODE_DATA_SEGMENT; + desc->dpl = dpl; + desc->present = 1; + + desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0; + // Must be set to 1 for code segments only. +} + + +static inline void +set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) +{ + clear_segment_descriptor(_desc); + clear_segment_descriptor(&_desc[1]); + + // The TSS descriptor is a special format in 64-bit mode, it is 16 bytes + // instead of 8. + tss_descriptor* desc = (tss_descriptor*)_desc; + + desc->base0 = base & 0xffffff; + desc->base1 = ((base) >> 24) & 0xff; + desc->base2 = ((base) >> 32); + desc->limit0 = limit & 0xffff; + desc->limit1 = (limit >> 16) & 0xf; + + desc->present = 1; + desc->type = DT_TSS; + desc->desc_type = DT_SYSTEM_SEGMENT; + desc->dpl = DPL_KERNEL; +} + + +#endif /* _ASSEMBLER */ + +#endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ diff --git a/src/system/boot/platform/bios_ia32/Jamfile b/src/system/boot/platform/bios_ia32/Jamfile index 6c0c273f88..347d2b420f 100644 --- a/src/system/boot/platform/bios_ia32/Jamfile +++ b/src/system/boot/platform/bios_ia32/Jamfile @@ -40,6 +40,8 @@ BootMergeObject boot_platform_bios_ia32.o : hpet.cpp interrupts.cpp interrupts_asm.S + long.cpp + long_asm.S # VESA/DDC EDID decode_edid.c diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp new file mode 100644 index 0000000000..829e2add72 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -0,0 +1,290 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +// Stop this from being included, it conflicts with the x86_64 version. +#define _KERNEL_ARCH_x86_DESCRIPTORS_H + + +#include "long.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "mmu.h" + + +struct gdt_idt_descr { + uint16 limit; + addr_t base; +} _PACKED; + + +/*! Convert a 32-bit address to a 64-bit address. */ +static inline uint64 +fix_address(uint64 address) +{ + return address - KERNEL_BASE + KERNEL_BASE_64BIT; +} + + +template +inline void +fix_address(FixedWidthPointer& p) +{ + if(p != NULL) + p.SetTo(fix_address(p.Get())); +} + + +static void +long_gdt_init() +{ + // Allocate memory for the GDT. + segment_descriptor* gdt = (segment_descriptor*) + mmu_allocate_page(&gKernelArgs.arch_args.phys_gdt); + gKernelArgs.arch_args.vir_gdt = fix_address((addr_t)gdt); + + dprintf("GDT at phys 0x%lx, virt 0x%llx\n", gKernelArgs.arch_args.phys_gdt, + gKernelArgs.arch_args.vir_gdt); + + clear_segment_descriptor(&gdt[0]); + + // Set up code/data segments (TSS segments set up later in the kernel). + set_segment_descriptor(&gdt[KERNEL_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY, + DPL_KERNEL); + set_segment_descriptor(&gdt[KERNEL_DATA_SEG / 8], DT_DATA_WRITEABLE, + DPL_KERNEL); + set_segment_descriptor(&gdt[USER_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY, + DPL_USER); + set_segment_descriptor(&gdt[USER_DATA_SEG / 8], DT_DATA_WRITEABLE, + DPL_USER); +} + + +static void +long_idt_init() +{ + interrupt_descriptor* idt = (interrupt_descriptor*) + mmu_allocate_page(&gKernelArgs.arch_args.phys_idt); + gKernelArgs.arch_args.vir_idt = fix_address((addr_t)idt); + + dprintf("IDT at phys 0x%lx, virt 0x%llx\n", gKernelArgs.arch_args.phys_idt, + gKernelArgs.arch_args.vir_idt); + + // The 32-bit kernel gets an IDT with the loader's exception handlers until + // it can set up its own. Can't do that here because they won't work after + // switching to long mode. Therefore, just clear the IDT and leave the + // kernel to set it up. + memset(idt, 0, B_PAGE_SIZE); +} + + +static void +long_mmu_init() +{ + addr_t physicalAddress; + + // Allocate the top level PML4. + uint64* pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir); + memset(pml4, 0, B_PAGE_SIZE); + gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4; + + // Identity map the first 1GB of memory, do so using large pages. + + uint64* pdpt = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pdpt, 0, B_PAGE_SIZE); + pml4[0] = physicalAddress | 0x3; + + uint64* pageDir = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pageDir, 0, B_PAGE_SIZE); + pdpt[0] = physicalAddress | 0x3; + + for (uint32 i = 0; i < 512; i++) { + pageDir[i] = (i * 0x200000) | 0x83; + } + + // Allocate tables for the kernel mappings. + + pdpt = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pdpt, 0, B_PAGE_SIZE); + pml4[511] = physicalAddress | 0x3; + + pageDir = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pageDir, 0, B_PAGE_SIZE); + pdpt[510] = physicalAddress | 0x3; + + // Store the virtual memory usage information. + gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT; + gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage(); + gKernelArgs.num_virtual_allocated_ranges = 1; + + // We can now allocate page tables and duplicate the mappings across from + // the 32-bit address space to them. + uint64* pageTable = NULL; + for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size + / B_PAGE_SIZE; i++) { + if ((i % 512) == 0) { + pageTable = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pageTable, 0, B_PAGE_SIZE); + pageDir[i / 512] = physicalAddress | 0x3; + + // Just performed another virtual allocation, account for it. + gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE; + } + + // Get the physical address to map. + if (!mmu_get_virtual_mapping(KERNEL_BASE + (i * B_PAGE_SIZE), + &physicalAddress)) + continue; + + pageTable[i % 512] = physicalAddress | 0x3; + } + + gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT + + gKernelArgs.virtual_allocated_range[0].size, 0x200000); + + // Sort the address ranges. + sort_address_ranges(gKernelArgs.physical_memory_range, + gKernelArgs.num_physical_memory_ranges); + sort_address_ranges(gKernelArgs.physical_allocated_range, + gKernelArgs.num_physical_allocated_ranges); + sort_address_ranges(gKernelArgs.virtual_allocated_range, + gKernelArgs.num_virtual_allocated_ranges); + + dprintf("phys memory ranges:\n"); + for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.physical_memory_range[i].start, + gKernelArgs.physical_memory_range[i].size); + } + + dprintf("allocated phys memory ranges:\n"); + for (uint32 i = 0; i < gKernelArgs.num_physical_allocated_ranges; i++) { + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.physical_allocated_range[i].start, + gKernelArgs.physical_allocated_range[i].size); + } + + dprintf("allocated virt memory ranges:\n"); + for (uint32 i = 0; i < gKernelArgs.num_virtual_allocated_ranges; i++) { + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.virtual_allocated_range[i].start, + gKernelArgs.virtual_allocated_range[i].size); + } +} + + +static void +convert_preloaded_image(preloaded_elf64_image* image) +{ + fix_address(image->next); + fix_address(image->name); + fix_address(image->debug_string_table); + fix_address(image->syms); + fix_address(image->rel); + fix_address(image->rela); + fix_address(image->pltrel); + fix_address(image->debug_symbols); +} + + +/*! Convert all addresses in kernel_args to 64-bit addresses. */ +static void +convert_kernel_args() +{ + fix_address(gKernelArgs.boot_volume); + fix_address(gKernelArgs.vesa_modes); + fix_address(gKernelArgs.edid_info); + fix_address(gKernelArgs.debug_output); + fix_address(gKernelArgs.boot_splash); + fix_address(gKernelArgs.arch_args.apic); + fix_address(gKernelArgs.arch_args.hpet); + + convert_preloaded_image(static_cast( + gKernelArgs.kernel_image.Pointer())); + fix_address(gKernelArgs.kernel_image); + + // Iterate over the preloaded images. Must save the next address before + // converting, as the next pointer will be converted. + preloaded_image* image = gKernelArgs.preloaded_images; + fix_address(gKernelArgs.preloaded_images); + while (image) { + preloaded_image* next = image->next; + convert_preloaded_image(static_cast(image)); + image = next; + } + + // Set correct kernel stack addresses. + for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) { + gKernelArgs.cpu_kstack[i].start + = fix_address(gKernelArgs.cpu_kstack[i].start); + } + + // Fix driver settings files. + driver_settings_file* file = gKernelArgs.driver_settings; + fix_address(gKernelArgs.driver_settings); + while (file) { + driver_settings_file* next = file->next; + fix_address(file->next); + fix_address(file->buffer); + file = next; + } +} + + +void +long_start_kernel() +{ + // Check whether long mode is supported. + cpuid_info info; + get_current_cpuid(&info, 0x80000001); + if ((info.regs.edx & (1<<29)) == 0) + panic("64-bit kernel requires a 64-bit CPU"); + + preloaded_elf64_image *image = static_cast( + gKernelArgs.kernel_image.Pointer()); + + // TODO: x86_64 SMP, disable for now. + gKernelArgs.num_cpus = 1; + + long_gdt_init(); + long_idt_init(); + long_mmu_init(); + convert_kernel_args(); + + debug_cleanup(); + + // Calculate the arguments for long_enter_kernel(). + uint64 entry = image->elf_header.e_entry; + uint64 stackTop = gKernelArgs.cpu_kstack[0].start + + gKernelArgs.cpu_kstack[0].size; + uint64 kernelArgs = fix_address((addr_t)&gKernelArgs); + + dprintf("kernel entry at 0x%llx, stack 0x%llx, args 0x%llx\n", entry, + stackTop, kernelArgs); + + // We're about to enter the kernel -- disable console output. + stdout = NULL; + + // Load the new GDT. The physical address is used because long_enter_kernel + // disables 32-bit paging. + gdt_idt_descr gdtr = { GDT_LIMIT - 1, gKernelArgs.arch_args.phys_gdt }; + asm volatile("lgdt %0" :: "m"(gdtr)); + + // Enter the kernel! + long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, entry, stackTop, + kernelArgs, 0); + panic("Shouldn't get here"); +} + diff --git a/src/system/boot/platform/bios_ia32/long.h b/src/system/boot/platform/bios_ia32/long.h new file mode 100644 index 0000000000..de2a0392c7 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/long.h @@ -0,0 +1,18 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef LONG_H +#define LONG_H + + +#include + + +extern "C" void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, + uint64 kernelArgs, int currentCPU); + +extern void long_start_kernel(); + + +#endif /* LONG_H */ diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S new file mode 100644 index 0000000000..d22355c647 --- /dev/null +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -0,0 +1,75 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + + +.code32 + + +/*! void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, + uint64 kernelArgs, int currentCPU); +*/ +FUNCTION(long_enter_kernel): + // Currently running with 32-bit paging tables at an identity mapped + // address. To switch to 64-bit paging we must first disable 32-bit paging, + // otherwise loading the new CR3 will fault. + movl %cr0, %eax + andl $~(1<<31), %eax + movl %eax, %cr0 + + // Enable PAE. + movl %cr4, %eax + orl $(1<<5), %eax + movl %eax, %cr4 + + // Point CR3 to the kernel's PML4. + movl 4(%esp), %eax + movl %eax, %cr3 + + // Enable long mode by setting EFER.LME. + movl $0xC0000080, %ecx + rdmsr + orl $(1<<8), %eax + wrmsr + + // Re-enable paging, which will put us in compatibility mode as we are + // currently in a 32-bit code segment. + movl %cr0, %ecx + orl $(1<<31), %ecx + movl %ecx, %cr0 + + // Jump into the 64-bit code segment. + ljmp $KERNEL_CODE_SEG, $.Llmode +.align 8 +.code64 +.Llmode: + // Set data segments. + mov $KERNEL_DATA_SEG, %ax + mov %ax, %ss + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + // Clear the high 32 bits of RSP. + movl %esp, %esp + + // Get the entry point address, arguments and new stack pointer. + movq 8(%rsp), %rax + movq 24(%rsp), %rdi + movl 32(%rsp), %esi + movq 16(%rsp), %rsp + + // Clear the stack frame/RFLAGS. + xorq %rbp, %rbp + push $0 + popf + + // Call the kernel entry point. + call *%rax diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index cfed3de612..93d1a1f193 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -419,6 +419,24 @@ mmu_allocate(void *virtualAddress, size_t size) } +/*! Allocates a single page and returns both its virtual and physical + addresses. +*/ +void * +mmu_allocate_page(addr_t *_physicalAddress) +{ + addr_t virt = get_next_virtual_page(); + addr_t phys = get_next_physical_page(); + + map_page(virt, phys, kDefaultPageFlags); + + if (_physicalAddress) + *_physicalAddress = phys; + + return (void *)virt; +} + + /*! Allocates the given physical range. \return \c true, if the range could be allocated, \c false otherwise. */ @@ -478,6 +496,35 @@ mmu_free(void *virtualAddress, size_t size) } +size_t +mmu_get_virtual_usage() +{ + return sNextVirtualAddress - KERNEL_BASE; +} + + +bool +mmu_get_virtual_mapping(addr_t virtualAddress, addr_t *_physicalAddress) +{ + if (virtualAddress < KERNEL_BASE) { + panic("mmu_get_virtual_mapping: asked to lookup invalid page %p!\n", + (void *)virtualAddress); + } + + uint32 *pageTable = (uint32 *)(sPageDirectory[virtualAddress + / (B_PAGE_SIZE * 1024)] & 0xfffff000); + uint32 tableEntry = pageTable[(virtualAddress % (B_PAGE_SIZE * 1024)) + / B_PAGE_SIZE]; + + if ((tableEntry & (1<<0)) != 0) { + *_physicalAddress = tableEntry & 0xFFFFF000; + return true; + } else { + return false; + } +} + + /*! Sets up the final and kernel accessible GDT and IDT tables. BIOS calls won't work any longer after this function has been called. @@ -501,10 +548,10 @@ mmu_init_for_kernel(void) map_page(gKernelArgs.arch_args.vir_idt, (uint32)idt, kDefaultPageFlags); // initialize it - interrupts_init_kernel_idt((void*)gKernelArgs.arch_args.vir_idt, + interrupts_init_kernel_idt((void*)(addr_t)gKernelArgs.arch_args.vir_idt, IDT_LIMIT); - TRACE("idt at virtual address 0x%lx\n", gKernelArgs.arch_args.vir_idt); + TRACE("idt at virtual address 0x%llx\n", gKernelArgs.arch_args.vir_idt); } // set up a new gdt @@ -524,7 +571,7 @@ mmu_init_for_kernel(void) // put standard segment descriptors in it segment_descriptor* virtualGDT - = (segment_descriptor*)gKernelArgs.arch_args.vir_gdt; + = (segment_descriptor*)(addr_t)gKernelArgs.arch_args.vir_gdt; clear_segment_descriptor(&virtualGDT[0]); // seg 0x08 - kernel 4GB code @@ -548,7 +595,7 @@ mmu_init_for_kernel(void) // load the GDT gdtDescriptor.limit = GDT_LIMIT - 1; - gdtDescriptor.base = (void*)gKernelArgs.arch_args.vir_gdt; + gdtDescriptor.base = (void*)(addr_t)gKernelArgs.arch_args.vir_gdt; asm("lgdt %0;" : : "m" (gdtDescriptor)); diff --git a/src/system/boot/platform/bios_ia32/mmu.h b/src/system/boot/platform/bios_ia32/mmu.h index fc197e98c8..9c59677094 100644 --- a/src/system/boot/platform/bios_ia32/mmu.h +++ b/src/system/boot/platform/bios_ia32/mmu.h @@ -20,9 +20,15 @@ extern void mmu_init(void); extern void mmu_init_for_kernel(void); extern addr_t mmu_map_physical_memory(addr_t physicalAddress, size_t size, uint32 flags); extern void *mmu_allocate(void *virtualAddress, size_t size); +extern void *mmu_allocate_page(addr_t *_physicalAddress); extern bool mmu_allocate_physical(addr_t base, size_t size); extern void mmu_free(void *virtualAddress, size_t size); +// Used by the long mode switch code +extern size_t mmu_get_virtual_usage(); +extern bool mmu_get_virtual_mapping(addr_t virtualAddress, + addr_t *_physicalAddress); + #ifdef __cplusplus } #endif diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 4bc2402866..a7ec21b11a 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -366,7 +366,7 @@ smp_cpu_ready(void) // Set up the final idt idt_descr.a = IDT_LIMIT - 1; - idt_descr.b = (uint32 *)gKernelArgs.arch_args.vir_idt; + idt_descr.b = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt; asm("lidt %0;" : : "m" (idt_descr)); diff --git a/src/system/boot/platform/bios_ia32/start.cpp b/src/system/boot/platform/bios_ia32/start.cpp index b15d539ccc..717b2c203b 100644 --- a/src/system/boot/platform/bios_ia32/start.cpp +++ b/src/system/boot/platform/bios_ia32/start.cpp @@ -22,6 +22,7 @@ #include "hpet.h" #include "interrupts.h" #include "keyboard.h" +#include "long.h" #include "mmu.h" #include "multiboot.h" #include "serial.h" @@ -75,6 +76,12 @@ platform_boot_options(void) extern "C" void platform_start_kernel(void) { + // 64-bit kernel entry is all handled in long.cpp + if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { + long_start_kernel(); + return; + } + static struct kernel_args *args = &gKernelArgs; // something goes wrong when we pass &gKernelArgs directly // to the assembler inline below - might be a bug in GCC diff --git a/src/system/boot/platform/pxe_ia32/Jamfile b/src/system/boot/platform/pxe_ia32/Jamfile index fe59db7dab..7adb3072ec 100644 --- a/src/system/boot/platform/pxe_ia32/Jamfile +++ b/src/system/boot/platform/pxe_ia32/Jamfile @@ -37,6 +37,8 @@ local bios_ia32_src = apm.cpp interrupts.cpp interrupts_asm.S + long.cpp + long_asm.S ; local bios_ia32_edid_src = diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 5ebb194bb1..c2b5a45454 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -817,7 +817,7 @@ arch_cpu_init_post_vm(kernel_args *args) uint32 i; // account for the segment descriptors - gGDT = (segment_descriptor *)args->arch_args.vir_gdt; + gGDT = (segment_descriptor *)(addr_t)args->arch_args.vir_gdt; create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 123f575bb3..ace0767439 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -553,7 +553,7 @@ arch_int_init(struct kernel_args *args) interrupt_handler_function** table; // set the global sIDT variable - sIDTs[0] = (desc_table *)args->arch_args.vir_idt; + sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt; // setup the standard programmable interrupt controller pic_init(); diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp index 9f84057e2d..674c4b5a60 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp @@ -266,7 +266,7 @@ X86PagingMethod32Bit::Init(kernel_args* args, TRACE("X86PagingMethod32Bit::Init(): entry\n"); // page hole set up in stage2 - fPageHole = (page_table_entry*)args->arch_args.page_hole; + fPageHole = (page_table_entry*)(addr_t)args->arch_args.page_hole; // calculate where the pgdir would be fPageHolePageDir = (page_directory_entry*) (((addr_t)args->arch_args.page_hole) @@ -276,7 +276,7 @@ X86PagingMethod32Bit::Init(kernel_args* args, sizeof(page_directory_entry) * NUM_USER_PGDIR_ENTS); fKernelPhysicalPageDirectory = args->arch_args.phys_pgdir; - fKernelVirtualPageDirectory = (page_directory_entry*) + fKernelVirtualPageDirectory = (page_directory_entry*)(addr_t) args->arch_args.vir_pgdir; #ifdef TRACE_X86_PAGING_METHOD_32_BIT diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp index e7001bb7c6..280dd143cb 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp @@ -56,7 +56,8 @@ struct X86PagingMethodPAE::ToPAESwitcher { fKernelArgs(args) { // page hole set up in the boot loader - fPageHole = (page_table_entry*)fKernelArgs->arch_args.page_hole; + fPageHole = (page_table_entry*) + (addr_t)fKernelArgs->arch_args.page_hole; // calculate where the page dir would be fPageHolePageDir = (page_directory_entry*) diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp index 6ce9648e39..125f28475a 100644 --- a/src/system/kernel/main.cpp +++ b/src/system/kernel/main.cpp @@ -78,6 +78,8 @@ static int32 main2(void *); extern "C" int _start(kernel_args *bootKernelArgs, int currentCPU) { + while (1) {} + if (bootKernelArgs->kernel_args_size != sizeof(kernel_args) || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) { // This is something we cannot handle right now - release kernels From 991e5bee90ffd98a39f012f6ce4e0740eb620073 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 26 Jun 2012 11:27:00 +0100 Subject: [PATCH 043/273] Pass correct kernel_args address to the kernel. --- src/system/boot/platform/bios_ia32/long.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 829e2add72..4ae8dc36d8 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -269,7 +269,7 @@ long_start_kernel() uint64 entry = image->elf_header.e_entry; uint64 stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; - uint64 kernelArgs = fix_address((addr_t)&gKernelArgs); + uint64 kernelArgs = (addr_t)&gKernelArgs; dprintf("kernel entry at 0x%llx, stack 0x%llx, args 0x%llx\n", entry, stackTop, kernelArgs); From b8a9a3a16073d8f474ee3415e208d04f4b58b4b0 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 26 Jun 2012 11:42:28 +0100 Subject: [PATCH 044/273] Copied the x86 debug console functions to x86_64. Note that this is only temporary so that I have serial output from the kernel, the x86 and x86_64 versions will be merged later. --- src/system/kernel/arch/x86_64/arch_cpu.cpp | 2 + .../kernel/arch/x86_64/arch_debug_console.cpp | 137 +++++++++++++++++- src/system/kernel/main.cpp | 2 - 3 files changed, 134 insertions(+), 7 deletions(-) diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp b/src/system/kernel/arch/x86_64/arch_cpu.cpp index 108b4d1621..64b8571115 100644 --- a/src/system/kernel/arch/x86_64/arch_cpu.cpp +++ b/src/system/kernel/arch/x86_64/arch_cpu.cpp @@ -30,6 +30,8 @@ arch_cpu_init_percpu(kernel_args *args, int cpu) status_t arch_cpu_init(kernel_args *args) { + dprintf("not implemented...\n"); + while (1); return B_OK; } diff --git a/src/system/kernel/arch/x86_64/arch_debug_console.cpp b/src/system/kernel/arch/x86_64/arch_debug_console.cpp index cae226df4b..8e5db41e05 100644 --- a/src/system/kernel/arch/x86_64/arch_debug_console.cpp +++ b/src/system/kernel/arch/x86_64/arch_debug_console.cpp @@ -1,13 +1,74 @@ /* + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de + * Copyright 2001, Rob Judd + * Copyright 2002, Marcus Overhagen * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. */ -#include +#include +#include +#include #include #include +#include +#include + +#include +#include + + +enum serial_register_offsets { + SERIAL_TRANSMIT_BUFFER = 0, + SERIAL_RECEIVE_BUFFER = 0, + SERIAL_DIVISOR_LATCH_LOW = 0, + SERIAL_DIVISOR_LATCH_HIGH = 1, + SERIAL_FIFO_CONTROL = 2, + SERIAL_LINE_CONTROL = 3, + SERIAL_MODEM_CONTROL = 4, + SERIAL_LINE_STATUS = 5, + SERIAL_MODEM_STATUS = 6, +}; + + +static const uint32 kSerialBaudRate = 115200; +static uint16 sSerialBasePort = 0x3f8; + // COM1 is the default debug output port + +static spinlock sSerialOutputSpinlock = B_SPINLOCK_INITIALIZER; + + +static void +init_serial_port(uint16 basePort, uint32 baudRate) +{ + sSerialBasePort = basePort; + + uint16 divisor = (uint16)(115200 / baudRate); + + out8(0x80, sSerialBasePort + SERIAL_LINE_CONTROL); /* set divisor latch access bit */ + out8(divisor & 0xf, sSerialBasePort + SERIAL_DIVISOR_LATCH_LOW); + out8(divisor >> 8, sSerialBasePort + SERIAL_DIVISOR_LATCH_HIGH); + out8(3, sSerialBasePort + SERIAL_LINE_CONTROL); /* 8N1 */ +} + + +static void +put_char(const char c) +{ + // wait until the transmitter empty bit is set + while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0) + asm volatile ("pause;"); + + out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER); +} + + +// #pragma mark - void @@ -43,43 +104,109 @@ arch_debug_blue_screen_getchar(void) int arch_debug_serial_try_getchar(void) { - return -1; + uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS); + if (lineStatus == 0xff) { + // The "data available" bit is set, but also all error bits. Likely we + // don't have a valid I/O port. + return -1; + } + + if ((lineStatus & 0x1) == 0) + return -1; + + return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER); } char arch_debug_serial_getchar(void) { - while(true) + while (true) { + uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS); + if (lineStatus == 0xff) { + // The "data available" bit is set, but also all error bits. Likely + // we don't have a valid I/O port. + return 0; + } + + if ((lineStatus & 0x1) != 0) + break; + PAUSE(); - return 0; + } + + return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER); } +static void +_arch_debug_serial_putchar(const char c) +{ + if (c == '\n') { + put_char('\r'); + put_char('\n'); + } else if (c != '\r') + put_char(c); +} + void arch_debug_serial_putchar(const char c) { + cpu_status state = 0; + if (!debug_debugger_running()) { + state = disable_interrupts(); + acquire_spinlock(&sSerialOutputSpinlock); + } + _arch_debug_serial_putchar(c); + + if (!debug_debugger_running()) { + release_spinlock(&sSerialOutputSpinlock); + restore_interrupts(state); + } } void arch_debug_serial_puts(const char *s) { + cpu_status state = 0; + if (!debug_debugger_running()) { + state = disable_interrupts(); + acquire_spinlock(&sSerialOutputSpinlock); + } + while (*s != '\0') { + _arch_debug_serial_putchar(*s); + s++; + } + + if (!debug_debugger_running()) { + release_spinlock(&sSerialOutputSpinlock); + restore_interrupts(state); + } } void arch_debug_serial_early_boot_message(const char *string) { - + // this function will only be called in fatal situations + // ToDo: also enable output via text console?! + arch_debug_console_init(NULL); + arch_debug_serial_puts(string); } status_t arch_debug_console_init(kernel_args *args) { + // only use the port if we could find one, else use the standard port + if (args != NULL && args->platform_args.serial_base_ports[0] != 0) + sSerialBasePort = args->platform_args.serial_base_ports[0]; + + init_serial_port(sSerialBasePort, kSerialBaudRate); + return B_OK; } diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp index 125f28475a..6ce9648e39 100644 --- a/src/system/kernel/main.cpp +++ b/src/system/kernel/main.cpp @@ -78,8 +78,6 @@ static int32 main2(void *); extern "C" int _start(kernel_args *bootKernelArgs, int currentCPU) { - while (1) {} - if (bootKernelArgs->kernel_args_size != sizeof(kernel_args) || bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) { // This is something we cannot handle right now - release kernels From 3f017e90611b6b53186f72bd9f6aa837d15e588a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 10:33:31 +0100 Subject: [PATCH 045/273] Also need to fix the kernel_args_range addresses. --- src/system/boot/platform/bios_ia32/long.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 4ae8dc36d8..cb7d2df295 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -225,10 +225,20 @@ convert_kernel_args() image = next; } + // Set correct kernel args range addresses. + dprintf("kernel args ranges:\n"); + for (uint32 i = 0; i < gKernelArgs.num_kernel_args_ranges; i++) { + gKernelArgs.kernel_args_range[i].start = fix_address( + gKernelArgs.kernel_args_range[i].start); + dprintf(" base %#018" B_PRIx64 ", length %#018" B_PRIx64 "\n", + gKernelArgs.kernel_args_range[i].start, + gKernelArgs.kernel_args_range[i].size); + } + // Set correct kernel stack addresses. for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) { - gKernelArgs.cpu_kstack[i].start - = fix_address(gKernelArgs.cpu_kstack[i].start); + gKernelArgs.cpu_kstack[i].start = fix_address( + gKernelArgs.cpu_kstack[i].start); } // Fix driver settings files. From 3403f23e81b7bd6e50c459d01ae7238c1f3f5984 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 11:23:54 +0100 Subject: [PATCH 046/273] Moved the common parts of arch_cpu.h between x86 and x86_64 to arch/common_x86/cpu.h. --- headers/private/kernel/arch/common_x86/cpu.h | 291 ++++++++++++++++++ headers/private/kernel/arch/x86/arch_cpu.h | 283 +---------------- headers/private/kernel/arch/x86_64/arch_cpu.h | 99 +++++- .../private/kernel/arch/x86_64/descriptors.h | 4 +- src/system/boot/platform/bios_ia32/long.cpp | 4 - src/system/boot/platform/bios_ia32/mmu.cpp | 1 + 6 files changed, 401 insertions(+), 281 deletions(-) create mode 100644 headers/private/kernel/arch/common_x86/cpu.h diff --git a/headers/private/kernel/arch/common_x86/cpu.h b/headers/private/kernel/arch/common_x86/cpu.h new file mode 100644 index 0000000000..82f94c69c6 --- /dev/null +++ b/headers/private/kernel/arch/common_x86/cpu.h @@ -0,0 +1,291 @@ +/* + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_COMMON_X86_CPU_H +#define _KERNEL_ARCH_COMMON_X86_CPU_H + + +#ifndef _ASSEMBLER +#include +#endif + + +#undef PAUSE +#define PAUSE() asm volatile ("pause;") + + +// MSR registers (possibly Intel specific) +#define IA32_MSR_TSC 0x10 +#define IA32_MSR_APIC_BASE 0x1b + +#define IA32_MSR_MTRR_CAPABILITIES 0xfe +#define IA32_MSR_SYSENTER_CS 0x174 +#define IA32_MSR_SYSENTER_ESP 0x175 +#define IA32_MSR_SYSENTER_EIP 0x176 +#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff +#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 +#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 + +// K8 MSR registers +#define K8_MSR_IPM 0xc0010055 + +// x86 features from cpuid eax 1, edx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) +#define IA32_FEATURE_FPU (1 << 0) // x87 fpu +#define IA32_FEATURE_VME (1 << 1) // virtual 8086 +#define IA32_FEATURE_DE (1 << 2) // debugging extensions +#define IA32_FEATURE_PSE (1 << 3) // page size extensions +#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction +#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction +#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing +#define IA32_FEATURE_MCE (1 << 7) // machine check exception +#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction +#define IA32_FEATURE_APIC (1 << 9) // local apic on chip +// (1 << 10) // Reserved +#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT +#define IA32_FEATURE_MTRR (1 << 12) // MTRR +#define IA32_FEATURE_PGE (1 << 13) // paging global bit +#define IA32_FEATURE_MCA (1 << 14) // machine check architecture +#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction +#define IA32_FEATURE_PAT (1 << 16) // page attribute table +#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages +#define IA32_FEATURE_PSN (1 << 18) // processor serial number +#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction +// (1 << 20) // Reserved +#define IA32_FEATURE_DS (1 << 21) // debug store +#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl +#define IA32_FEATURE_MMX (1 << 23) // mmx instructions +#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction +#define IA32_FEATURE_SSE (1 << 25) // SSE +#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 +#define IA32_FEATURE_SS (1 << 27) // self snoop +#define IA32_FEATURE_HTT (1 << 28) // hyperthreading +#define IA32_FEATURE_TM (1 << 29) // thermal monitor +#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 +#define IA32_FEATURE_PBE (1 << 31) // pending break enable + +// x86 features from cpuid eax 1, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) +#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 +#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction +#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store +#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT +#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store +#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions +#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions +#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep +#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 +#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 +#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID +// (1 << 11) // Reserved +#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add +#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B +#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control +#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability +// (1 << 16) // Reserved +#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers +#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access +#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 +#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 +#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support +#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction +#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction +#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline +#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions +#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States +#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE +#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions +#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion +#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction +#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor + +// x86 features from cpuid eax 0x80000001, edx register (AMD) +// only care about the ones that are unique to this register +#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET +#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit +#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions +#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR +#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction +#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode +#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions +#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! + +// x86 defined features from cpuid eax 6, eax register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor +#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology +#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer +#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification +#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty +#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management + +// x86 defined features from cpuid eax 6, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF +#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS + +// cr4 flags +#define IA32_CR4_PAE (1UL << 5) +#define IA32_CR4_GLOBAL_PAGES (1UL << 7) + +// Memory type ranges +#define IA32_MTR_UNCACHED 0 +#define IA32_MTR_WRITE_COMBINING 1 +#define IA32_MTR_WRITE_THROUGH 4 +#define IA32_MTR_WRITE_PROTECTED 5 +#define IA32_MTR_WRITE_BACK 6 + +// EFLAGS register +#define X86_EFLAGS_CARRY 0x00000001 +#define X86_EFLAGS_RESERVED1 0x00000002 +#define X86_EFLAGS_PARITY 0x00000004 +#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 +#define X86_EFLAGS_ZERO 0x00000040 +#define X86_EFLAGS_SIGN 0x00000080 +#define X86_EFLAGS_TRAP 0x00000100 +#define X86_EFLAGS_INTERRUPT 0x00000200 +#define X86_EFLAGS_DIRECTION 0x00000400 +#define X86_EFLAGS_OVERFLOW 0x00000800 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 +#define X86_EFLAGS_NESTED_TASK 0x00004000 +#define X86_EFLAGS_RESUME 0x00010000 +#define X86_EFLAGS_V86_MODE 0x00020000 +#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 +#define X86_EFLAGS_ID 0x00200000 + +#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ + | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ + | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) + + +#ifndef _ASSEMBLER + + +typedef struct x86_mtrr_info { + uint64 base; + uint64 size; + uint8 type; +} x86_mtrr_info; + +typedef struct x86_optimized_functions { + void (*memcpy)(void* dest, const void* source, size_t count); + void* memcpy_end; + void (*memset)(void* dest, int value, size_t count); + void* memset_end; +} x86_optimized_functions; + +typedef struct x86_cpu_module_info { + module_info info; + uint32 (*count_mtrrs)(void); + void (*init_mtrrs)(void); + + void (*set_mtrr)(uint32 index, uint64 base, uint64 length, + uint8 type); + status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, + uint8* _type); + void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, + uint32 count); + + void (*get_optimized_functions)(x86_optimized_functions* functions); +} x86_cpu_module_info; + +// features +enum x86_feature_type { + FEATURE_COMMON = 0, // cpuid eax=1, ecx register + FEATURE_EXT, // cpuid eax=1, edx register + FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) + FEATURE_6_EAX, // cpuid eax=6, eax registers + FEATURE_6_ECX, // cpuid eax=6, ecx registers + + FEATURE_NUM +}; + +enum x86_vendors { + VENDOR_INTEL = 0, + VENDOR_AMD, + VENDOR_CYRIX, + VENDOR_UMC, + VENDOR_NEXGEN, + VENDOR_CENTAUR, + VENDOR_RISE, + VENDOR_TRANSMETA, + VENDOR_NSC, + + VENDOR_NUM, + VENDOR_UNKNOWN, +}; + + +#define nop() __asm__ ("nop"::) + +#define read_cr3(value) \ + __asm__("mov %%cr3,%0" : "=r" (value)) + +#define write_cr3(value) \ + __asm__("mov %0,%%cr3" : : "r" (value)) + +#define read_dr3(value) \ + __asm__("mov %%dr3,%0" : "=r" (value)) + +#define write_dr3(value) \ + __asm__("mov %0,%%dr3" : : "r" (value)) + +#define invalidate_TLB(va) \ + __asm__("invlpg (%0)" : : "r" (va)) + +#define wbinvd() \ + __asm__("wbinvd") + +#define out8(value,port) \ + __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) + +#define out16(value,port) \ + __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) + +#define out32(value,port) \ + __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) + +#define in8(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in16(port) ({ \ + uint16 _v; \ + __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in32(port) ({ \ + uint32 _v; \ + __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define out8_p(value,port) \ + __asm__ ("outb %%al,%%dx\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : : "a" (value), "d" (port)) + +#define in8_p(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + + +#endif // !_ASSEMBLER + +#endif /* _KERNEL_ARCH_COMMON_X86_CPU_H */ diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 4365fe13ca..cfe380c820 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -9,164 +9,13 @@ #define _KERNEL_ARCH_x86_CPU_H +#include "../common_x86/cpu.h" + #ifndef _ASSEMBLER - -#include -#include - -#endif // !_ASSEMBLER - - -#undef PAUSE -#define PAUSE() asm volatile ("pause;") - - -// MSR registers (possibly Intel specific) -#define IA32_MSR_TSC 0x10 -#define IA32_MSR_APIC_BASE 0x1b - -#define IA32_MSR_MTRR_CAPABILITIES 0xfe -#define IA32_MSR_SYSENTER_CS 0x174 -#define IA32_MSR_SYSENTER_ESP 0x175 -#define IA32_MSR_SYSENTER_EIP 0x176 -#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff -#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 -#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 - -// K8 MSR registers -#define K8_MSR_IPM 0xc0010055 - -// x86 features from cpuid eax 1, edx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) -#define IA32_FEATURE_FPU (1 << 0) // x87 fpu -#define IA32_FEATURE_VME (1 << 1) // virtual 8086 -#define IA32_FEATURE_DE (1 << 2) // debugging extensions -#define IA32_FEATURE_PSE (1 << 3) // page size extensions -#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction -#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction -#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing -#define IA32_FEATURE_MCE (1 << 7) // machine check exception -#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction -#define IA32_FEATURE_APIC (1 << 9) // local apic on chip -// (1 << 10) // Reserved -#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT -#define IA32_FEATURE_MTRR (1 << 12) // MTRR -#define IA32_FEATURE_PGE (1 << 13) // paging global bit -#define IA32_FEATURE_MCA (1 << 14) // machine check architecture -#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction -#define IA32_FEATURE_PAT (1 << 16) // page attribute table -#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages -#define IA32_FEATURE_PSN (1 << 18) // processor serial number -#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction -// (1 << 20) // Reserved -#define IA32_FEATURE_DS (1 << 21) // debug store -#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl -#define IA32_FEATURE_MMX (1 << 23) // mmx instructions -#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction -#define IA32_FEATURE_SSE (1 << 25) // SSE -#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 -#define IA32_FEATURE_SS (1 << 27) // self snoop -#define IA32_FEATURE_HTT (1 << 28) // hyperthreading -#define IA32_FEATURE_TM (1 << 29) // thermal monitor -#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 -#define IA32_FEATURE_PBE (1 << 31) // pending break enable - -// x86 features from cpuid eax 1, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) -#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 -#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction -#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store -#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT -#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store -#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions -#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions -#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep -#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 -#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 -#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID -// (1 << 11) // Reserved -#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add -#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B -#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control -#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability -// (1 << 16) // Reserved -#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers -#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access -#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 -#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 -#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support -#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction -#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction -#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline -#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions -#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States -#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE -#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions -#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion -#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction -#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor - -// x86 features from cpuid eax 0x80000001, edx register (AMD) -// only care about the ones that are unique to this register -#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET -#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit -#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions -#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR -#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction -#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode -#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions -#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! - -// x86 defined features from cpuid eax 6, eax register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor -#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology -#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer -#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification -#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty -#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management - -// x86 defined features from cpuid eax 6, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF -#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS - -// cr4 flags -#define IA32_CR4_PAE (1UL << 5) -#define IA32_CR4_GLOBAL_PAGES (1UL << 7) - -// Memory type ranges -#define IA32_MTR_UNCACHED 0 -#define IA32_MTR_WRITE_COMBINING 1 -#define IA32_MTR_WRITE_THROUGH 4 -#define IA32_MTR_WRITE_PROTECTED 5 -#define IA32_MTR_WRITE_BACK 6 - - -// EFLAGS register -#define X86_EFLAGS_CARRY 0x00000001 -#define X86_EFLAGS_RESERVED1 0x00000002 -#define X86_EFLAGS_PARITY 0x00000004 -#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 -#define X86_EFLAGS_ZERO 0x00000040 -#define X86_EFLAGS_SIGN 0x00000080 -#define X86_EFLAGS_TRAP 0x00000100 -#define X86_EFLAGS_INTERRUPT 0x00000200 -#define X86_EFLAGS_DIRECTION 0x00000400 -#define X86_EFLAGS_OVERFLOW 0x00000800 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 -#define X86_EFLAGS_NESTED_TASK 0x00004000 -#define X86_EFLAGS_RESUME 0x00010000 -#define X86_EFLAGS_V86_MODE 0x00020000 -#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 -#define X86_EFLAGS_ID 0x00200000 - -#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ - | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ - | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) +# ifndef _BOOT_MODE +# include +# endif +#endif // iframe types @@ -179,36 +28,6 @@ struct X86PagingStructures; - -typedef struct x86_mtrr_info { - uint64 base; - uint64 size; - uint8 type; -} x86_mtrr_info; - -typedef struct x86_optimized_functions { - void (*memcpy)(void* dest, const void* source, size_t count); - void* memcpy_end; - void (*memset)(void* dest, int value, size_t count); - void* memset_end; -} x86_optimized_functions; - -typedef struct x86_cpu_module_info { - module_info info; - uint32 (*count_mtrrs)(void); - void (*init_mtrrs)(void); - - void (*set_mtrr)(uint32 index, uint64 base, uint64 length, - uint8 type); - status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, - uint8* _type); - void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, - uint32 count); - - void (*get_optimized_functions)(x86_optimized_functions* functions); -} x86_cpu_module_info; - - struct tss { uint16 prev_task; uint16 unused0; @@ -289,32 +108,6 @@ struct vm86_iframe { || ((f)->flags & 0x20000) != 0) #define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) -// features -enum x86_feature_type { - FEATURE_COMMON = 0, // cpuid eax=1, ecx register - FEATURE_EXT, // cpuid eax=1, edx register - FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) - FEATURE_6_EAX, // cpuid eax=6, eax registers - FEATURE_6_ECX, // cpuid eax=6, ecx registers - - FEATURE_NUM -}; - -enum x86_vendors { - VENDOR_INTEL = 0, - VENDOR_AMD, - VENDOR_CYRIX, - VENDOR_UMC, - VENDOR_NEXGEN, - VENDOR_CENTAUR, - VENDOR_RISE, - VENDOR_TRANSMETA, - VENDOR_NSC, - - VENDOR_NUM, - VENDOR_UNKNOWN, -}; - typedef struct arch_cpu_info { // saved cpu info enum x86_vendors vendor; @@ -338,11 +131,11 @@ typedef struct arch_cpu_info { struct tss double_fault_tss; } arch_cpu_info; + #ifdef __cplusplus extern "C" { #endif -#define nop() __asm__ ("nop"::) struct arch_thread; @@ -384,67 +177,9 @@ void x86_double_fault_exception(struct iframe* frame); void x86_page_fault_exception_double_fault(struct iframe* frame); -#define read_cr3(value) \ - __asm__("movl %%cr3,%0" : "=r" (value)) - -#define write_cr3(value) \ - __asm__("movl %0,%%cr3" : : "r" (value)) - -#define read_dr3(value) \ - __asm__("movl %%dr3,%0" : "=r" (value)) - -#define write_dr3(value) \ - __asm__("movl %0,%%dr3" : : "r" (value)) - -#define invalidate_TLB(va) \ - __asm__("invlpg (%0)" : : "r" (va)) - -#define wbinvd() \ - __asm__("wbinvd") - -#define out8(value,port) \ - __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) - -#define out16(value,port) \ - __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) - -#define out32(value,port) \ - __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) - -#define in8(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in16(port) ({ \ - uint16 _v; \ - __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in32(port) ({ \ - uint32 _v; \ - __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define out8_p(value,port) \ - __asm__ ("outb %%al,%%dx\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : : "a" (value), "d" (port)) - -#define in8_p(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - +#ifndef _BOOT_MODE extern segment_descriptor* gGDT; +#endif #ifdef __cplusplus diff --git a/headers/private/kernel/arch/x86_64/arch_cpu.h b/headers/private/kernel/arch/x86_64/arch_cpu.h index f1d56b9fb5..fa0d657006 100644 --- a/headers/private/kernel/arch/x86_64/arch_cpu.h +++ b/headers/private/kernel/arch/x86_64/arch_cpu.h @@ -1,6 +1,103 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_ARCH_X86_64_CPU_H #define _KERNEL_ARCH_X86_64_CPU_H -#include "../x86/arch_cpu.h" + +#include "../common_x86/cpu.h" + +#ifndef _ASSEMBLER +# ifndef _BOOT_MODE +# include +# endif +#endif + + +// iframe types +#define IFRAME_TYPE_SYSCALL 0x1 +#define IFRAME_TYPE_OTHER 0x2 +#define IFRAME_TYPE_MASK 0xf + + +#ifndef _ASSEMBLER + + +struct tss { + uint32 _reserved1; + uint64 rsp0; + uint64 rsp1; + uint64 rsp2; + uint64 _reserved2; + uint64 ist1; + uint64 ist2; + uint64 ist3; + uint64 ist4; + uint64 ist5; + uint64 ist6; + uint64 ist7; + uint64 _reserved3; + uint16 _reserved4; + uint16 io_bitmap; +} _PACKED; + + +struct iframe { + unsigned long type; + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rbp; + unsigned long rsi; + unsigned long rdi; + unsigned long rdx; + unsigned long rcx; + unsigned long rbx; + unsigned long rax; + unsigned long vector; + unsigned long error_code; + unsigned long rip; + unsigned long cs; + unsigned long flags; + + // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). + unsigned long user_rsp; + unsigned long user_ss; +} _PACKED; + +#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG) + + +typedef struct arch_cpu_info { + // CPU identification/feature information. + enum x86_vendors vendor; + uint32 feature[FEATURE_NUM]; + char model_name[49]; + const char* vendor_name; + int type; + int family; + int extended_family; + int stepping; + int model; + int extended_model; + + // TSS and double fault TSS for this CPU. + struct tss tss; + struct tss double_fault_tss; +} arch_cpu_info; + + +#ifndef _BOOT_MODE +extern segment_descriptor* gGDT; +#endif + + +#endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_X86_64_CPU_H */ diff --git a/headers/private/kernel/arch/x86_64/descriptors.h b/headers/private/kernel/arch/x86_64/descriptors.h index a1850f0dd1..c52d8945cb 100644 --- a/headers/private/kernel/arch/x86_64/descriptors.h +++ b/headers/private/kernel/arch/x86_64/descriptors.h @@ -10,8 +10,8 @@ // Note that the ordering of these is important to SYSCALL/SYSRET. #define KERNEL_CODE_SEG 0x08 #define KERNEL_DATA_SEG 0x10 -#define USER_DATA_SEG 0x18 -#define USER_CODE_SEG 0x20 +#define USER_DATA_SEG 0x1b +#define USER_CODE_SEG 0x23 #ifndef _ASSEMBLER diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index cb7d2df295..bae7f59d9c 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -4,10 +4,6 @@ */ -// Stop this from being included, it conflicts with the x86_64 version. -#define _KERNEL_ARCH_x86_DESCRIPTORS_H - - #include "long.h" #include diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 93d1a1f193..ba4779e255 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include From 45e0e08aed9ff534cc6e90b71542ed272de100c1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 15:07:45 +0100 Subject: [PATCH 047/273] Made panic() safe to use before the current thread has been set. --- src/system/kernel/debug/debug.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index 1b5d12df37..df7e2efa74 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -2066,7 +2066,8 @@ panic(const char* format, ...) cpu_status state = disable_interrupts(); - kernel_debugger_internal("PANIC: ", format, args, smp_get_current_cpu()); + kernel_debugger_internal("PANIC: ", format, args, + thread_get_current_thread() ? smp_get_current_cpu() : 0); restore_interrupts(state); From 014f4403ee33035722b1414fda1e16bc6f7ef2be Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 15:11:06 +0100 Subject: [PATCH 048/273] Use unsigned long, not uint32, for the 'l' qualifier in printf() - long is 64-bit on x86_64. --- src/system/kernel/lib/kernel_vsprintf.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/lib/kernel_vsprintf.cpp b/src/system/kernel/lib/kernel_vsprintf.cpp index 5fbad19693..25c275c54f 100644 --- a/src/system/kernel/lib/kernel_vsprintf.cpp +++ b/src/system/kernel/lib/kernel_vsprintf.cpp @@ -450,11 +450,11 @@ vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args) } if (qualifier == 'L') - num = va_arg(args, uint64); + num = va_arg(args, unsigned long long); else if (qualifier == 'l') { - num = va_arg(args, uint32); + num = va_arg(args, unsigned long); if ((flags & SIGN) != 0) - num = (ssize_t)num; + num = (long)num; } else if (qualifier == 'z') { num = va_arg(args, size_t); if ((flags & SIGN) != 0) From c9f6d2271fc105de01b1359d66c5304c75bd396d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 15:15:53 +0100 Subject: [PATCH 049/273] x86_64: Implemented exception handling. --- headers/private/kernel/arch/common_x86/cpu.h | 3 + headers/private/kernel/arch/x86_64/arch_cpu.h | 5 +- .../kernel/arch/x86_64/arch_kernel_args.h | 8 + .../private/kernel/arch/x86_64/descriptors.h | 35 +++- src/system/boot/platform/bios_ia32/long.cpp | 6 - src/system/kernel/arch/x86_64/Jamfile | 1 + src/system/kernel/arch/x86_64/arch_cpu.cpp | 51 +++--- src/system/kernel/arch/x86_64/arch_int.cpp | 160 +++++++++++++++++- .../kernel/arch/x86_64/arch_interrupts.S | 143 ++++++++++++++++ src/system/kernel/arch/x86_64/asm_offsets.cpp | 17 +- 10 files changed, 373 insertions(+), 56 deletions(-) create mode 100644 src/system/kernel/arch/x86_64/arch_interrupts.S diff --git a/headers/private/kernel/arch/common_x86/cpu.h b/headers/private/kernel/arch/common_x86/cpu.h index 82f94c69c6..f825d13567 100644 --- a/headers/private/kernel/arch/common_x86/cpu.h +++ b/headers/private/kernel/arch/common_x86/cpu.h @@ -225,6 +225,9 @@ enum x86_vendors { #define nop() __asm__ ("nop"::) +#define read_cr2(value) \ + __asm__("mov %%cr2,%0" : "=r" (value)) + #define read_cr3(value) \ __asm__("mov %%cr3,%0" : "=r" (value)) diff --git a/headers/private/kernel/arch/x86_64/arch_cpu.h b/headers/private/kernel/arch/x86_64/arch_cpu.h index fa0d657006..0eda6fae36 100644 --- a/headers/private/kernel/arch/x86_64/arch_cpu.h +++ b/headers/private/kernel/arch/x86_64/arch_cpu.h @@ -71,7 +71,7 @@ struct iframe { unsigned long user_ss; } _PACKED; -#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG) +#define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) typedef struct arch_cpu_info { @@ -87,9 +87,8 @@ typedef struct arch_cpu_info { int model; int extended_model; - // TSS and double fault TSS for this CPU. + // TSS for this CPU. struct tss tss; - struct tss double_fault_tss; } arch_cpu_info; diff --git a/headers/private/kernel/arch/x86_64/arch_kernel_args.h b/headers/private/kernel/arch/x86_64/arch_kernel_args.h index 78c54547e0..1ccfd8db41 100644 --- a/headers/private/kernel/arch/x86_64/arch_kernel_args.h +++ b/headers/private/kernel/arch/x86_64/arch_kernel_args.h @@ -1,6 +1,14 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ #ifndef _KERNEL_ARCH_X86_64_KERNEL_ARGS_H #define _KERNEL_ARCH_X86_64_KERNEL_ARGS_H + +// x86_64 kernel is loaded loaded by the x86 bootloader, kernel_args is +// identical to x86. #include "../x86/arch_kernel_args.h" + #endif /* _KERNEL_ARCH_X86_64_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/arch/x86_64/descriptors.h b/headers/private/kernel/arch/x86_64/descriptors.h index c52d8945cb..41e268adf8 100644 --- a/headers/private/kernel/arch/x86_64/descriptors.h +++ b/headers/private/kernel/arch/x86_64/descriptors.h @@ -59,13 +59,21 @@ struct interrupt_descriptor { uint32 base0 : 16; uint32 sel : 16; uint32 ist : 3; - uint32 unused : 5; - uint32 flags : 8; + uint32 unused1 : 5; + uint32 type : 4; + uint32 unused2 : 1; + uint32 dpl : 2; + uint32 present : 1; uint32 base1 : 16; uint32 base2 : 32; uint32 reserved : 32; } _PACKED; +struct gdt_idt_descr { + uint16 limit; + addr_t base; +} _PACKED; + enum descriptor_privilege_levels { DPL_KERNEL = 0, DPL_USER = 3, @@ -90,6 +98,11 @@ enum descriptor_types { DT_CODE_DATA_SEGMENT = 1, }; +enum gate_types { + GATE_INTERRUPT = 14, + GATE_TRAP = 15, +}; + static inline void clear_segment_descriptor(segment_descriptor* desc) @@ -144,6 +157,24 @@ set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) } +static inline void +set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type, + uint16 seg, uint32 dpl, uint32 ist) +{ + desc->base0 = (addr & 0xFFFF); + desc->base1 = ((addr >> 16) & 0xFFFF); + desc->base2 = ((addr >> 32) & 0xFFFFFFFF); + desc->sel = seg; + desc->ist = ist; + desc->type = type; + desc->dpl = dpl; + desc->present = 1; + desc->unused1 = 0; + desc->unused2 = 0; + desc->reserved = 0; +} + + #endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index bae7f59d9c..608f918f34 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -20,12 +20,6 @@ #include "mmu.h" -struct gdt_idt_descr { - uint16 limit; - addr_t base; -} _PACKED; - - /*! Convert a 32-bit address to a 64-bit address. */ static inline uint64 fix_address(uint64 address) diff --git a/src/system/kernel/arch/x86_64/Jamfile b/src/system/kernel/arch/x86_64/Jamfile index 9765aad4f0..3f32a22ad3 100644 --- a/src/system/kernel/arch/x86_64/Jamfile +++ b/src/system/kernel/arch/x86_64/Jamfile @@ -13,6 +13,7 @@ KernelMergeObject kernel_arch_x86_64.o : arch_debug_console.cpp arch_elf.cpp arch_int.cpp + arch_interrupts.S arch_platform.cpp arch_real_time_clock.cpp arch_smp.cpp diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp b/src/system/kernel/arch/x86_64/arch_cpu.cpp index 64b8571115..2141b86aa6 100644 --- a/src/system/kernel/arch/x86_64/arch_cpu.cpp +++ b/src/system/kernel/arch/x86_64/arch_cpu.cpp @@ -14,37 +14,35 @@ status_t -arch_cpu_preboot_init_percpu(kernel_args *args, int cpu) +arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) { return B_OK; } status_t -arch_cpu_init_percpu(kernel_args *args, int cpu) +arch_cpu_init_percpu(kernel_args* args, int cpu) { return B_OK; } status_t -arch_cpu_init(kernel_args *args) -{ - dprintf("not implemented...\n"); - while (1); - return B_OK; -} - - -status_t -arch_cpu_init_post_vm(kernel_args *args) +arch_cpu_init(kernel_args* args) { return B_OK; } status_t -arch_cpu_init_post_modules(kernel_args *args) +arch_cpu_init_post_vm(kernel_args* args) +{ + return B_OK; +} + + +status_t +arch_cpu_init_post_modules(kernel_args* args) { return B_OK; } @@ -79,8 +77,8 @@ arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) ssize_t -arch_cpu_user_strlcpy(char *to, const char *from, size_t size, - addr_t *faultHandler) +arch_cpu_user_strlcpy(char* to, const char* from, size_t size, + addr_t* faultHandler) { int fromLength = 0; addr_t oldFaultHandler = *faultHandler; @@ -99,6 +97,7 @@ arch_cpu_user_strlcpy(char *to, const char *from, size_t size, break; } } + // count any leftover from chars while (*from++ != '\0') { fromLength++; @@ -114,11 +113,11 @@ error: status_t -arch_cpu_user_memcpy(void *to, const void *from, size_t size, - addr_t *faultHandler) +arch_cpu_user_memcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) { - char *d = (char *)to; - const char *s = (const char *)from; + char* d = (char*)to; + const char* s = (const char*)from; addr_t oldFaultHandler = *faultHandler; // this check is to trick the gcc4 compiler and have it keep the error label @@ -141,9 +140,9 @@ error: status_t -arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) +arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) { - char *xs = (char *)s; + char* xs = (char*)s; addr_t oldFaultHandler = *faultHandler; // this check is to trick the gcc4 compiler and have it keep the error label @@ -179,24 +178,22 @@ arch_cpu_idle(void) void -arch_cpu_sync_icache(void *address, size_t length) +arch_cpu_sync_icache(void* address, size_t length) { - // instruction cache is always consistent on x86 + // Instruction cache is always consistent on x86. } void arch_cpu_memory_read_barrier(void) { - asm volatile ("lock;" : : : "memory"); - asm volatile ("addl $0, 0(%%esp);" : : : "memory"); + asm volatile("lfence" : : : "memory"); } void arch_cpu_memory_write_barrier(void) { - asm volatile ("lock;" : : : "memory"); - asm volatile ("addl $0, 0(%%esp);" : : : "memory"); + asm volatile("sfence" : : : "memory"); } diff --git a/src/system/kernel/arch/x86_64/arch_int.cpp b/src/system/kernel/arch/x86_64/arch_int.cpp index b196a92476..8b84ea143c 100644 --- a/src/system/kernel/arch/x86_64/arch_int.cpp +++ b/src/system/kernel/arch/x86_64/arch_int.cpp @@ -6,7 +6,102 @@ #include -#include +#include +#include + +#include +#include + +#include + + +typedef void interrupt_handler_function(iframe* frame); + +static const char *kInterruptNames[] = { + /* 0 */ "Divide Error Exception", + /* 1 */ "Debug Exception", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint Exception", + /* 4 */ "Overflow Exception", + /* 5 */ "BOUND Range Exceeded Exception", + /* 6 */ "Invalid Opcode Exception", + /* 7 */ "Device Not Available Exception", + /* 8 */ "Double Fault Exception", + /* 9 */ "Coprocessor Segment Overrun", + /* 10 */ "Invalid TSS Exception", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Fault Exception", + /* 13 */ "General Protection Exception", + /* 14 */ "Page-Fault Exception", + /* 15 */ "-", + /* 16 */ "x87 FPU Floating-Point Error", + /* 17 */ "Alignment Check Exception", + /* 18 */ "Machine-Check Exception", + /* 19 */ "SIMD Floating-Point Exception", +}; + +static const uint32 kInterruptHandlerTableSize = 256; + +static interrupt_descriptor* sIDT; +interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; + +extern uint8 isr_array[kInterruptHandlerTableSize][16]; + + +static const char* +exception_name(unsigned long number, char* buffer, size_t bufferSize) +{ + if (number >= 0 + && number < (sizeof(kInterruptNames) / sizeof(kInterruptNames[0]))) + return kInterruptNames[number]; + + snprintf(buffer, bufferSize, "exception %lu", number); + return buffer; +} + + +static void +invalid_exception(iframe* frame) +{ + char name[32]; + panic("unhandled trap 0x%lx (%s) at ip 0x%lx\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->rip); +} + + +static void +fatal_exception(iframe *frame) +{ + char name[32]; + panic("fatal exception 0x%lx (%s) at ip 0x%lx, error code 0x%lx\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->rip, frame->error_code); +} + + +static void +unexpected_exception(iframe* frame) +{ + char name[32]; + panic("fatal exception 0x%lx (%s) at ip 0x%lx, error code 0x%lx\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->rip, frame->error_code); +} + + +static void +page_fault_exception(iframe* frame) +{ + unsigned long cr2; + read_cr2(cr2); + + panic("page fault exception at ip 0x%lx on 0x%lx, error code 0x%lx\n", + frame->rip, cr2, frame->error_code); +} + + +// #pragma mark - void @@ -31,14 +126,71 @@ arch_int_configure_io_interrupt(int irq, uint32 config) status_t -arch_int_init(struct kernel_args *args) +arch_int_init(kernel_args* args) { + // The loader allocates an empty IDT for us. + sIDT = (interrupt_descriptor*)args->arch_args.vir_idt; + + // Fill out the IDT, pointing each entry to the corresponding entry in the + // ISR array created in arch_interrupts.S (see there to see how this works). + for(uint32 i = 0; i < kInterruptHandlerTableSize; i++) { + // x86_64 removes task gates, therefore we cannot use a separate TSS + // for the double fault exception. However, instead it adds a new stack + // switching mechanism, the IST. The IST is a table of stack addresses + // in the TSS. If the IST field of an interrupt descriptor is non-zero, + // the CPU will switch to the stack specified by that IST entry when + // handling that interrupt. So, we use IST entry 1 to store the double + // fault stack address (this is set up in arch_cpu.cpp). + uint32 ist = (i == 8) ? 1 : 0; + + set_interrupt_descriptor(&sIDT[i], (addr_t)&isr_array[i], + GATE_INTERRUPT, KERNEL_CODE_SEG, DPL_KERNEL, ist); + } + + interrupt_handler_function** table = gInterruptHandlerTable; + + // Initialize the interrupt handler table. + for (uint32 i = 0; i < ARCH_INTERRUPT_BASE; i++) + table[i] = invalid_exception; + //for (uint32 i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) + // table[i] = hardware_interrupt; + + table[0] = unexpected_exception; // Divide Error Exception (#DE) + //table[1] = x86_handle_debug_exception; // Debug Exception (#DB) + table[1] = unexpected_exception; + table[2] = fatal_exception; // NMI Interrupt + //table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) + table[3] = unexpected_exception; + table[4] = unexpected_exception; // Overflow Exception (#OF) + table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = fatal_exception; // Device Not Available Exception (#NM) + table[8] = fatal_exception; // Double Fault Exception (#DF) + table[9] = fatal_exception; // Coprocessor Segment Overrun + table[10] = fatal_exception; // Invalid TSS Exception (#TS) + table[11] = fatal_exception; // Segment Not Present (#NP) + table[12] = fatal_exception; // Stack Fault Exception (#SS) + table[13] = unexpected_exception; // General Protection Exception (#GP) + table[14] = page_fault_exception; // Page-Fault Exception (#PF) + table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = unexpected_exception; // Alignment Check Exception (#AC) + table[18] = fatal_exception; // Machine-Check Exception (#MC) + table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + + // Load the IDT. + gdt_idt_descr idtr = { + 256 * sizeof(interrupt_descriptor) - 1, + (addr_t)sIDT + }; + asm volatile("lidt %0" :: "m"(idtr)); + + panic("not implemented\n"); return B_OK; } status_t -arch_int_init_post_vm(struct kernel_args *args) +arch_int_init_post_vm(kernel_args* args) { return B_OK; } @@ -52,7 +204,7 @@ arch_int_init_io(kernel_args* args) status_t -arch_int_init_post_device_manager(struct kernel_args *args) +arch_int_init_post_device_manager(kernel_args* args) { return B_OK; } diff --git a/src/system/kernel/arch/x86_64/arch_interrupts.S b/src/system/kernel/arch/x86_64/arch_interrupts.S new file mode 100644 index 0000000000..908a2d4940 --- /dev/null +++ b/src/system/kernel/arch/x86_64/arch_interrupts.S @@ -0,0 +1,143 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + +#include "asm_offsets.h" + + +// Push the remainder of the interrupt frame onto the stack. +#define PUSH_IFRAME_BOTTOM(iframeType) \ + push %rax; \ + push %rbx; \ + push %rcx; \ + push %rdx; \ + push %rdi; \ + push %rsi; \ + push %rbp; \ + push %r8; \ + push %r9; \ + push %r10; \ + push %r11; \ + push %r12; \ + push %r13; \ + push %r14; \ + push %r15; \ + push $iframeType; + +// Restore the interrupt frame. +#define RESTORE_IFRAME() \ + add $8, %rsp; \ + pop %r15; \ + pop %r14; \ + pop %r13; \ + pop %r12; \ + pop %r11; \ + pop %r10; \ + pop %r9; \ + pop %r8; \ + pop %rbp; \ + pop %rsi; \ + pop %rdi; \ + pop %rdx; \ + pop %rcx; \ + pop %rbx; \ + pop %rax; + +// The following code defines the interrupt service routines for all 256 +// interrupts. It creates a block of handlers, each 16 bytes, that the IDT +// initialization code just loops through. + +// Interrupt with no error code, pushes a 0 error code. +#define DEFINE_ISR(nr) \ + .align 16; \ + push $0; \ + push $nr; \ + jmp int_bottom; + +// Interrupt with an error code. +#define DEFINE_ISR_E(nr) \ + .align 16; \ + push $nr; \ + jmp int_bottom; + +// Array of interrupt service routines. +.align 16 +SYMBOL(isr_array): + // Exceptions (0-19) and reserved interrupts (20-31). + DEFINE_ISR(0) + DEFINE_ISR(1) + DEFINE_ISR(2) + DEFINE_ISR(3) + DEFINE_ISR(4) + DEFINE_ISR(5) + DEFINE_ISR(6) + DEFINE_ISR(7) + DEFINE_ISR_E(8) + DEFINE_ISR(9) + DEFINE_ISR_E(10) + DEFINE_ISR_E(11) + DEFINE_ISR_E(12) + DEFINE_ISR_E(13) + DEFINE_ISR_E(14) + DEFINE_ISR(15) + DEFINE_ISR(16) + DEFINE_ISR_E(17) + DEFINE_ISR(18) + DEFINE_ISR(19) + DEFINE_ISR(20) + DEFINE_ISR(21) + DEFINE_ISR(22) + DEFINE_ISR(23) + DEFINE_ISR(24) + DEFINE_ISR(25) + DEFINE_ISR(26) + DEFINE_ISR(27) + DEFINE_ISR(28) + DEFINE_ISR(29) + DEFINE_ISR(30) + DEFINE_ISR(31) + + // User-defined ISRs (32-255) - none take an error code. + .Lintr = 32 + .rept 224 + DEFINE_ISR(.Lintr) + .Lintr = .Lintr+1 + .endr + +// Common interrupt handling code. +FUNCTION(int_bottom): + // If coming from user-mode, need to load the kernel GS segment base. + testl $3, 24(%rsp) + jz 1f + swapgs +1: + // Push the rest of the interrupt frame to the stack. + PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) + + cld + + // Frame pointer is the iframe. + movq %rsp, %rbp + + // Call the interrupt handler. + movq %rsp, %rdi + movq IFRAME_vector(%rsp), %rax + call *gInterruptHandlerTable(, %rax, 8) + + // Restore the saved registers. + RESTORE_IFRAME() + + // Get rid of the error code and interrupt number, restore the previous + // GS base if returning to user-mode, and return. + addq $16, %rsp + testl $3, 8(%rsp) + jz 2f + swapgs +2: iretq diff --git a/src/system/kernel/arch/x86_64/asm_offsets.cpp b/src/system/kernel/arch/x86_64/asm_offsets.cpp index 1ac18010a4..b09f817534 100644 --- a/src/system/kernel/arch/x86_64/asm_offsets.cpp +++ b/src/system/kernel/arch/x86_64/asm_offsets.cpp @@ -11,7 +11,7 @@ #include -//#include +#include //#include //#include //#include @@ -45,19 +45,8 @@ dummy() //DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); // struct iframe - //DEFINE_SIZEOF_MACRO(IFRAME, iframe); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, eax); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, edx); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, eip); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); - //DEFINE_OFFSET_MACRO(IFRAME, iframe, user_esp); - - // struct vm86_iframe - //DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); - //DEFINE_OFFSET_MACRO(VM86_IFRAME, vm86_iframe, flags); + DEFINE_SIZEOF_MACRO(IFRAME, iframe); + DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); // struct syscall_info //DEFINE_SIZEOF_MACRO(SYSCALL_INFO, syscall_info); From 0705884ac415022fb9c734da089fe3dd5a06873a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 27 Jun 2012 15:48:39 +0100 Subject: [PATCH 050/273] Style fixes. --- headers/private/kernel/arch/x86_64/descriptors.h | 14 +++++++------- src/system/boot/platform/bios_ia32/long.cpp | 12 ++++++------ src/system/boot/platform/bios_ia32/long_asm.S | 8 ++++---- src/system/kernel/arch/x86_64/arch_int.cpp | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/headers/private/kernel/arch/x86_64/descriptors.h b/headers/private/kernel/arch/x86_64/descriptors.h index 41e268adf8..445682ca1c 100644 --- a/headers/private/kernel/arch/x86_64/descriptors.h +++ b/headers/private/kernel/arch/x86_64/descriptors.h @@ -120,8 +120,8 @@ set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) // it always treats base as 0 and does no limit checks. desc->base0 = 0; desc->base1 = 0; - desc->limit0 = 0xFFFF; - desc->limit1 = 0xF; + desc->limit0 = 0xffff; + desc->limit1 = 0xf; desc->granularity = 1; desc->type = type; @@ -145,8 +145,8 @@ set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) tss_descriptor* desc = (tss_descriptor*)_desc; desc->base0 = base & 0xffffff; - desc->base1 = ((base) >> 24) & 0xff; - desc->base2 = ((base) >> 32); + desc->base1 = (base >> 24) & 0xff; + desc->base2 = (base >> 32); desc->limit0 = limit & 0xffff; desc->limit1 = (limit >> 16) & 0xf; @@ -161,9 +161,9 @@ static inline void set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type, uint16 seg, uint32 dpl, uint32 ist) { - desc->base0 = (addr & 0xFFFF); - desc->base1 = ((addr >> 16) & 0xFFFF); - desc->base2 = ((addr >> 32) & 0xFFFFFFFF); + desc->base0 = addr & 0xffff; + desc->base1 = (addr >> 16) & 0xffff; + desc->base2 = (addr >> 32) & 0xffffffff; desc->sel = seg; desc->ist = ist; desc->type = type; diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 608f918f34..cafc2ed3a2 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -32,7 +32,7 @@ template inline void fix_address(FixedWidthPointer& p) { - if(p != NULL) + if (p != NULL) p.SetTo(fix_address(p.Get())); } @@ -69,7 +69,7 @@ long_idt_init() mmu_allocate_page(&gKernelArgs.arch_args.phys_idt); gKernelArgs.arch_args.vir_idt = fix_address((addr_t)idt); - dprintf("IDT at phys 0x%lx, virt 0x%llx\n", gKernelArgs.arch_args.phys_idt, + dprintf("IDT at phys %#lx, virt %#llx\n", gKernelArgs.arch_args.phys_idt, gKernelArgs.arch_args.vir_idt); // The 32-bit kernel gets an IDT with the loader's exception handlers until @@ -209,7 +209,7 @@ convert_kernel_args() // converting, as the next pointer will be converted. preloaded_image* image = gKernelArgs.preloaded_images; fix_address(gKernelArgs.preloaded_images); - while (image) { + while (image != NULL) { preloaded_image* next = image->next; convert_preloaded_image(static_cast(image)); image = next; @@ -234,7 +234,7 @@ convert_kernel_args() // Fix driver settings files. driver_settings_file* file = gKernelArgs.driver_settings; fix_address(gKernelArgs.driver_settings); - while (file) { + while (file != NULL) { driver_settings_file* next = file->next; fix_address(file->next); fix_address(file->buffer); @@ -249,7 +249,7 @@ long_start_kernel() // Check whether long mode is supported. cpuid_info info; get_current_cpuid(&info, 0x80000001); - if ((info.regs.edx & (1<<29)) == 0) + if ((info.regs.edx & (1 << 29)) == 0) panic("64-bit kernel requires a 64-bit CPU"); preloaded_elf64_image *image = static_cast( @@ -271,7 +271,7 @@ long_start_kernel() + gKernelArgs.cpu_kstack[0].size; uint64 kernelArgs = (addr_t)&gKernelArgs; - dprintf("kernel entry at 0x%llx, stack 0x%llx, args 0x%llx\n", entry, + dprintf("kernel entry at %#llx, stack %#llx, args %#llx\n", entry, stackTop, kernelArgs); // We're about to enter the kernel -- disable console output. diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index d22355c647..3a52720077 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -20,12 +20,12 @@ FUNCTION(long_enter_kernel): // address. To switch to 64-bit paging we must first disable 32-bit paging, // otherwise loading the new CR3 will fault. movl %cr0, %eax - andl $~(1<<31), %eax + andl $~(1 << 31), %eax movl %eax, %cr0 // Enable PAE. movl %cr4, %eax - orl $(1<<5), %eax + orl $(1 << 5), %eax movl %eax, %cr4 // Point CR3 to the kernel's PML4. @@ -35,13 +35,13 @@ FUNCTION(long_enter_kernel): // Enable long mode by setting EFER.LME. movl $0xC0000080, %ecx rdmsr - orl $(1<<8), %eax + orl $(1 << 8), %eax wrmsr // Re-enable paging, which will put us in compatibility mode as we are // currently in a 32-bit code segment. movl %cr0, %ecx - orl $(1<<31), %ecx + orl $(1 << 31), %ecx movl %ecx, %cr0 // Jump into the 64-bit code segment. diff --git a/src/system/kernel/arch/x86_64/arch_int.cpp b/src/system/kernel/arch/x86_64/arch_int.cpp index 8b84ea143c..dcab07ec0d 100644 --- a/src/system/kernel/arch/x86_64/arch_int.cpp +++ b/src/system/kernel/arch/x86_64/arch_int.cpp @@ -17,7 +17,7 @@ typedef void interrupt_handler_function(iframe* frame); -static const char *kInterruptNames[] = { +static const char* kInterruptNames[] = { /* 0 */ "Divide Error Exception", /* 1 */ "Debug Exception", /* 2 */ "NMI Interrupt", @@ -64,17 +64,17 @@ static void invalid_exception(iframe* frame) { char name[32]; - panic("unhandled trap 0x%lx (%s) at ip 0x%lx\n", + panic("unhandled trap %#lx (%s) at ip %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), frame->rip); } static void -fatal_exception(iframe *frame) +fatal_exception(iframe* frame) { char name[32]; - panic("fatal exception 0x%lx (%s) at ip 0x%lx, error code 0x%lx\n", + panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), frame->rip, frame->error_code); } @@ -84,7 +84,7 @@ static void unexpected_exception(iframe* frame) { char name[32]; - panic("fatal exception 0x%lx (%s) at ip 0x%lx, error code 0x%lx\n", + panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), frame->rip, frame->error_code); } @@ -96,7 +96,7 @@ page_fault_exception(iframe* frame) unsigned long cr2; read_cr2(cr2); - panic("page fault exception at ip 0x%lx on 0x%lx, error code 0x%lx\n", + panic("page fault exception at ip %#lx on %#lx, error code %#lx\n", frame->rip, cr2, frame->error_code); } From 294711f98c107cf2d9d05b7fc34cd863e87bd358 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 28 Jun 2012 12:36:45 +0100 Subject: [PATCH 051/273] Changed {,u}int64 to be long rather than long long on x86_64. --- headers/config/types.h | 39 ++++++++++--------- .../kernel/debug/debug_builtin_commands.cpp | 6 +-- src/system/kernel/debug/debug_parser.cpp | 6 +-- src/system/kernel/debug/debug_variables.cpp | 8 ++-- src/system/kernel/debug/tracing.cpp | 9 +++-- .../kernel/device_manager/IORequest.cpp | 10 ++--- src/system/kernel/device_manager/devfs.cpp | 8 ++-- .../kernel/device_manager/legacy_drivers.cpp | 4 +- .../kernel/disk_device_manager/KPartition.cpp | 6 +-- src/system/kernel/int.cpp | 8 ++-- src/system/kernel/real_time_clock.cpp | 4 +- src/system/kernel/thread.cpp | 14 +++---- src/system/kernel/vm/VMAnonymousCache.cpp | 8 ++-- src/system/kernel/vm/VMCache.cpp | 4 +- src/system/kernel/vm/vm.cpp | 4 +- 15 files changed, 71 insertions(+), 67 deletions(-) diff --git a/headers/config/types.h b/headers/config/types.h index 8da83ecabd..13f1dc0ac4 100644 --- a/headers/config/types.h +++ b/headers/config/types.h @@ -20,9 +20,13 @@ typedef signed short __haiku_std_int16; typedef unsigned short __haiku_std_uint16; typedef signed int __haiku_std_int32; typedef unsigned int __haiku_std_uint32; +#ifdef __HAIKU_ARCH_64_BIT +typedef signed long __haiku_std_int64; +typedef unsigned long __haiku_std_uint64; +#else typedef signed long long __haiku_std_int64; typedef unsigned long long __haiku_std_uint64; - // TODO: on x86_64 these should be long +#endif typedef __haiku_std_int8 __haiku_int8; typedef __haiku_std_uint8 __haiku_uint8; @@ -43,16 +47,11 @@ typedef signed long int __haiku_saddr_t; typedef unsigned long int __haiku_addr_t; #ifdef __HAIKU_ARCH_PHYSICAL_64_BIT -# if __HAIKU_ARCH_64_BIT - typedef signed long int __haiku_phys_saddr_t; - typedef unsigned long int __haiku_phys_addr_t; -# else - typedef signed long long __haiku_phys_saddr_t; - typedef unsigned long long __haiku_phys_addr_t; -# endif + typedef __haiku_int64 __haiku_phys_saddr_t; + typedef __haiku_uint64 __haiku_phys_addr_t; #else - typedef signed long int __haiku_phys_saddr_t; - typedef unsigned long int __haiku_phys_addr_t; + typedef __haiku_int32 __haiku_phys_saddr_t; + typedef __haiku_uint32 __haiku_phys_addr_t; #endif /* address type limits */ @@ -77,21 +76,25 @@ typedef unsigned long int __haiku_addr_t; /* printf()/scanf() format prefixes */ #define __HAIKU_STD_PRI_PREFIX_32 "" -#define __HAIKU_STD_PRI_PREFIX_64 "ll" +#ifdef __HAIKU_ARCH_64_BIT +# define __HAIKU_STD_PRI_PREFIX_64 "l" +#else +# define __HAIKU_STD_PRI_PREFIX_64 "ll" +#endif #ifdef __HAIKU_BEOS_COMPATIBLE_TYPES -# define __HAIKU_PRI_PREFIX_32 "l" +# define __HAIKU_PRI_PREFIX_32 "l" #else -# define __HAIKU_PRI_PREFIX_32 __HAIKU_STD_PRI_PREFIX_32 +# define __HAIKU_PRI_PREFIX_32 __HAIKU_STD_PRI_PREFIX_32 #endif -#define __HAIKU_PRI_PREFIX_64 __HAIKU_STD_PRI_PREFIX_64 +#define __HAIKU_PRI_PREFIX_64 __HAIKU_STD_PRI_PREFIX_64 -#define __HAIKU_PRI_PREFIX_ADDR "l" +#define __HAIKU_PRI_PREFIX_ADDR "l" -#if __HAIKU_ARCH_PHYSICAL_64_BIT && !__HAIKU_ARCH_64_BIT -# define __HAIKU_PRI_PREFIX_PHYS_ADDR "ll" +#ifdef __HAIKU_ARCH_PHYSICAL_64_BIT +# define __HAIKU_PRI_PREFIX_PHYS_ADDR __HAIKU_PRI_PREFIX_64 #else -# define __HAIKU_PRI_PREFIX_PHYS_ADDR "l" +# define __HAIKU_PRI_PREFIX_PHYS_ADDR __HAIKU_PRI_PREFIX_32 #endif diff --git a/src/system/kernel/debug/debug_builtin_commands.cpp b/src/system/kernel/debug/debug_builtin_commands.cpp index 32f7445783..3648e9794f 100644 --- a/src/system/kernel/debug/debug_builtin_commands.cpp +++ b/src/system/kernel/debug/debug_builtin_commands.cpp @@ -91,7 +91,7 @@ cmd_expr(int argc, char **argv) uint64 result; if (evaluate_debug_expression(argv[1], &result, false)) { - kprintf("%llu (0x%llx)\n", result, result); + kprintf("%" B_PRIu64 " (0x%" B_PRIx64 ")\n", result, result); set_debug_variable("_", result); } @@ -291,8 +291,8 @@ cmd_wc(int argc, char** argv) const char* line = argv[1]; if (line == NULL) { // last run -- print results - kprintf("%10lld %10lld %10lld\n", userData->lines, userData->words, - userData->chars); + kprintf("%10" B_PRIu64 " %10" B_PRIu64 " %10" B_PRIu64 "\n", + userData->lines, userData->words, userData->chars); return 0; } diff --git a/src/system/kernel/debug/debug_parser.cpp b/src/system/kernel/debug/debug_parser.cpp index 87f50c5474..2a0398ce57 100644 --- a/src/system/kernel/debug/debug_parser.cpp +++ b/src/system/kernel/debug/debug_parser.cpp @@ -845,7 +845,7 @@ ExpressionParser::_ParseArgument(int& argc, char** argv) fTokenizer.SetCommandMode(true); _EatToken(TOKEN_CLOSING_PARENTHESIS); - snprintf(sTempBuffer, sizeof(sTempBuffer), "%llu", value); + snprintf(sTempBuffer, sizeof(sTempBuffer), "%" B_PRIu64, value); _AddArgument(argc, argv, sTempBuffer); return true; } @@ -857,7 +857,7 @@ ExpressionParser::_ParseArgument(int& argc, char** argv) uint64 value = _ParseCommandPipe(returnValue); _EatToken(TOKEN_CLOSING_BRACKET); - snprintf(sTempBuffer, sizeof(sTempBuffer), "%llu", value); + snprintf(sTempBuffer, sizeof(sTempBuffer), "%" B_PRIu64, value); _AddArgument(argc, argv, sTempBuffer); return true; } @@ -1050,7 +1050,7 @@ ExpressionParser::_ParseDereference(void** _address, uint32* _size) if (size != 1 && size != 2 && size != 4 && size != 8) { snprintf(sTempBuffer, sizeof(sTempBuffer), - "invalid size (%llu) for unary * operator", size); + "invalid size (%" B_PRIu64 ") for unary * operator", size); parse_exception(sTempBuffer, position); } diff --git a/src/system/kernel/debug/debug_variables.cpp b/src/system/kernel/debug/debug_variables.cpp index fe8c0dbc84..92ae27c820 100644 --- a/src/system/kernel/debug/debug_variables.cpp +++ b/src/system/kernel/debug/debug_variables.cpp @@ -226,8 +226,8 @@ cmd_variables(int argc, char **argv) for (int i = 0; i < kVariableCount; i++) { Variable& variable = sVariables[i]; if (variable.IsUsed()) { - kprintf("%16s: %llu (0x%llx)\n", variable.name, variable.value, - variable.value); + kprintf("%16s: %" B_PRIu64 " (0x%" B_PRIx64 ")\n", variable.name, + variable.value, variable.value); } } @@ -235,8 +235,8 @@ cmd_variables(int argc, char **argv) for (int i = 0; i < kTemporaryVariableCount; i++) { Variable& variable = sTemporaryVariables[i]; if (variable.IsUsed()) { - kprintf("%16s: %llu (0x%llx)\n", variable.name, variable.value, - variable.value); + kprintf("%16s: %" B_PRIu64 " (0x%" B_PRIx64 ")\n", variable.name, + variable.value, variable.value); } } diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index 3ec01ee14d..04763b8766 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -806,9 +806,10 @@ AbstractTraceEntry::Dump(TraceOutput& out) : fTime; if (out.Flags() & TRACE_OUTPUT_TEAM_ID) - out.Print("[%6" B_PRId32 ":%6" B_PRId32 "] %10Ld: ", fThread, fTeam, time); + out.Print("[%6" B_PRId32 ":%6" B_PRId32 "] %10" B_PRId64 ": ", fThread, + fTeam, time); else - out.Print("[%6" B_PRId32 "] %10Ld: ", fThread, time); + out.Print("[%6" B_PRId32 "] %10" B_PRId64 ": ", fThread, time); AddDump(out); @@ -994,7 +995,7 @@ public: { // TODO: this is *very* slow char buffer[64]; - snprintf(buffer, sizeof(buffer), "%Ld", fValue); + snprintf(buffer, sizeof(buffer), "%" B_PRId64, fValue); return strstr(out.DumpEntry(entry), buffer) != NULL; } }; @@ -1005,7 +1006,7 @@ public: { // TODO: this is *very* slow char buffer[64]; - snprintf(buffer, sizeof(buffer), "%Lx", fValue); + snprintf(buffer, sizeof(buffer), "%" B_PRIx64, fValue); return strstr(out.DumpEntry(entry), buffer) != NULL; } }; diff --git a/src/system/kernel/device_manager/IORequest.cpp b/src/system/kernel/device_manager/IORequest.cpp index 494417ff36..c573ac1b97 100644 --- a/src/system/kernel/device_manager/IORequest.cpp +++ b/src/system/kernel/device_manager/IORequest.cpp @@ -664,8 +664,8 @@ IOOperation::Dump() const kprintf(" parent: %p\n", fParent); kprintf(" status: %s\n", strerror(fStatus)); kprintf(" dma buffer: %p\n", fDMABuffer); - kprintf(" offset: %-8Ld (original: %Ld)\n", fOffset, - fOriginalOffset); + kprintf(" offset: %-8" B_PRIdOFF " (original: %" B_PRIdOFF ")\n", + fOffset, fOriginalOffset); kprintf(" length: %-8" B_PRIuGENADDR " (original: %" B_PRIuGENADDR ")\n", fLength, fOriginalLength); kprintf(" transferred: %" B_PRIuGENADDR "\n", fTransferredBytes); @@ -1162,8 +1162,8 @@ IORequest::_CopyData(void* _buffer, off_t offset, size_t size, bool copyIn) uint8* buffer = (uint8*)_buffer; if (offset < fOffset || offset + (off_t)size > fOffset + (off_t)fLength) { - panic("IORequest::_CopyData(): invalid range: (%lld, %lu)", offset, - size); + panic("IORequest::_CopyData(): invalid range: (%" B_PRIdOFF ", %lu)", + offset, size); return B_BAD_VALUE; } @@ -1281,7 +1281,7 @@ IORequest::Dump() const kprintf(" status: %s\n", strerror(fStatus)); kprintf(" mutex: %p\n", &fLock); kprintf(" IOBuffer: %p\n", fBuffer); - kprintf(" offset: %Ld\n", fOffset); + kprintf(" offset: %" B_PRIdOFF "\n", fOffset); kprintf(" length: %" B_PRIuGENADDR "\n", fLength); kprintf(" transfer size: %" B_PRIuGENADDR "\n", fTransferSize); kprintf(" relative offset: %" B_PRIuGENADDR "\n", fRelativeParentOffset); diff --git a/src/system/kernel/device_manager/devfs.cpp b/src/system/kernel/device_manager/devfs.cpp index efb66e3fa3..5ae4783abf 100644 --- a/src/system/kernel/device_manager/devfs.cpp +++ b/src/system/kernel/device_manager/devfs.cpp @@ -802,7 +802,7 @@ dump_node(int argc, char** argv) } kprintf("DEVFS NODE: %p\n", vnode); - kprintf(" id: %Ld\n", vnode->id); + kprintf(" id: %" B_PRIdINO "\n", vnode->id); kprintf(" name: \"%s\"\n", vnode->name); kprintf(" type: %x\n", vnode->stream.type); kprintf(" parent: %p\n", vnode->parent); @@ -814,7 +814,7 @@ dump_node(int argc, char** argv) devfs_vnode* children = vnode->stream.u.dir.dir_head; while (children != NULL) { - kprintf(" %p, id %Ld\n", children, children->id); + kprintf(" %p, id %" B_PRIdINO "\n", children, children->id); children = children->dir_next; } } else if (S_ISLNK(vnode->stream.type)) { @@ -826,8 +826,8 @@ dump_node(int argc, char** argv) partition_info& info = vnode->stream.u.dev.partition->info; kprintf(" raw device node: %p\n", vnode->stream.u.dev.partition->raw_device); - kprintf(" offset: %Ld\n", info.offset); - kprintf(" size: %Ld\n", info.size); + kprintf(" offset: %" B_PRIdOFF "\n", info.offset); + kprintf(" size: %" B_PRIdOFF "\n", info.size); kprintf(" block size: %" B_PRId32 "\n", info.logical_block_size); kprintf(" session: %" B_PRId32 "\n", info.session); kprintf(" partition: %" B_PRId32 "\n", info.partition); diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index 9d41ee1580..da7a6a4aa3 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -664,7 +664,7 @@ load_driver_symbols(const char *driverName) static status_t reload_driver(legacy_driver *driver) { - dprintf("devfs: reload driver \"%s\" (%" B_PRIdDEV ", %lld)\n", + dprintf("devfs: reload driver \"%s\" (%" B_PRIdDEV ", %" B_PRIdINO ")\n", driver->name, driver->device, driver->node); unload_driver(driver); @@ -827,7 +827,7 @@ dump_driver(legacy_driver* driver) kprintf(" path: %s\n", driver->path); kprintf(" image: %" B_PRId32 "\n", driver->image); kprintf(" device: %" B_PRIdDEV "\n", driver->device); - kprintf(" node: %Ld\n", driver->node); + kprintf(" node: %" B_PRIdINO "\n", driver->node); kprintf(" last modified: %" B_PRIdTIME ".%ld\n", driver->last_modified.tv_sec, driver->last_modified.tv_nsec); kprintf(" devs used: %" B_PRIu32 "\n", driver->devices_used); diff --git a/src/system/kernel/disk_device_manager/KPartition.cpp b/src/system/kernel/disk_device_manager/KPartition.cpp index dcaafb94af..878ab99a79 100644 --- a/src/system/kernel/disk_device_manager/KPartition.cpp +++ b/src/system/kernel/disk_device_manager/KPartition.cpp @@ -1303,10 +1303,10 @@ KPartition::Dump(bool deep, int32 level) GetPath(&path); if (level > 0) OUT("%spartition %" B_PRId32 ": %s\n", prefix, ID(), path.Path()); - OUT("%s offset: %lld\n", prefix, Offset()); - OUT("%s size: %lld (%.2f MB)\n", prefix, Size(), + OUT("%s offset: %" B_PRIdOFF "\n", prefix, Offset()); + OUT("%s size: %" B_PRIdOFF " (%.2f MB)\n", prefix, Size(), Size() / (1024.0*1024)); - OUT("%s content size: %lld\n", prefix, ContentSize()); + OUT("%s content size: %" B_PRIdOFF "\n", prefix, ContentSize()); OUT("%s block size: %" B_PRIu32 "\n", prefix, BlockSize()); OUT("%s child count: %" B_PRId32 "\n", prefix, CountChildren()); OUT("%s index: %" B_PRId32 "\n", prefix, Index()); diff --git a/src/system/kernel/int.cpp b/src/system/kernel/int.cpp index 59c9671814..9916e4b718 100644 --- a/src/system/kernel/int.cpp +++ b/src/system/kernel/int.cpp @@ -80,9 +80,9 @@ dump_int_statistics(int argc, char **argv) && sVectors[i].handler_list == NULL) continue; - kprintf("int %3d, enabled %" B_PRId32 ", handled %8lld, unhandled %8lld%s%s\n", - i, sVectors[i].enable_count, sVectors[i].handled_count, - sVectors[i].unhandled_count, + kprintf("int %3d, enabled %" B_PRId32 ", handled %8" B_PRId64 ", " + "unhandled %8" B_PRId64 "%s%s\n", i, sVectors[i].enable_count, + sVectors[i].handled_count,sVectors[i].unhandled_count, B_SPINLOCK_IS_LOCKED(&sVectors[i].vector_lock) ? ", ACTIVE" : "", sVectors[i].handler_list == NULL ? ", no handler" : ""); @@ -106,7 +106,7 @@ dump_int_statistics(int argc, char **argv) if (io->no_handled_info) kprintf("\n"); else - kprintf("%8lld\n", io->handled_count); + kprintf("%8" B_PRId64 "\n", io->handled_count); } kprintf("\n"); diff --git a/src/system/kernel/real_time_clock.cpp b/src/system/kernel/real_time_clock.cpp index b73c8f920f..11f5f43a96 100644 --- a/src/system/kernel/real_time_clock.cpp +++ b/src/system/kernel/real_time_clock.cpp @@ -84,8 +84,8 @@ rtc_debug(int argc, char **argv) = arch_rtc_get_system_time_offset(sRealTimeData); currentTime = (systemTimeOffset + system_time()) / 1000000; - dprintf("system_time: %Ld\n", system_time()); - dprintf("system_time_offset: %Ld\n", systemTimeOffset); + dprintf("system_time: %" B_PRId64 "\n", system_time()); + dprintf("system_time_offset: %" B_PRId64 "\n", systemTimeOffset); dprintf("current_time: %" B_PRIu32 "\n", currentTime); } else { // If there was an argument, reset the system and hw time. diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index fc5859c5ab..f392756e8c 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -1685,11 +1685,11 @@ _dump_thread_info(Thread *thread, bool shortInfo) kprintf("(%d)\n", thread->cpu->cpu_num); else kprintf("\n"); - kprintf("sig_pending: %#llx (blocked: %#llx" - ", before sigsuspend(): %#llx)\n", - (long long)thread->ThreadPendingSignals(), - (long long)thread->sig_block_mask, - (long long)thread->sigsuspend_original_unblocked_mask); + kprintf("sig_pending: %#" B_PRIx64 " (blocked: %#" B_PRIx64 + ", before sigsuspend(): %#" B_PRIx64 ")\n", + (int64)thread->ThreadPendingSignals(), + (int64)thread->sig_block_mask, + (int64)thread->sigsuspend_original_unblocked_mask); kprintf("in_kernel: %d\n", thread->in_kernel); if (thread->state == B_THREAD_WAITING) { @@ -1756,8 +1756,8 @@ _dump_thread_info(Thread *thread, bool shortInfo) kprintf("user_thread: %p\n", (void *)thread->user_thread); kprintf("kernel_errno: %#x (%s)\n", thread->kernel_errno, strerror(thread->kernel_errno)); - kprintf("kernel_time: %Ld\n", thread->kernel_time); - kprintf("user_time: %Ld\n", thread->user_time); + kprintf("kernel_time: %" B_PRId64 "\n", thread->kernel_time); + kprintf("user_time: %" B_PRId64 "\n", thread->user_time); kprintf("flags: 0x%" B_PRIx32 "\n", thread->flags); kprintf("architecture dependant section:\n"); arch_thread_dump_info(&thread->arch_info); diff --git a/src/system/kernel/vm/VMAnonymousCache.cpp b/src/system/kernel/vm/VMAnonymousCache.cpp index 9f0f834974..28ba8c6e8a 100644 --- a/src/system/kernel/vm/VMAnonymousCache.cpp +++ b/src/system/kernel/vm/VMAnonymousCache.cpp @@ -999,8 +999,8 @@ VMAnonymousCache::_Commit(off_t size, int priority) off_t toReserve = size - committed_size; if (vm_try_reserve_memory(toReserve, priority, 1000000) != B_OK) { - dprintf("%p->VMAnonymousCache::_Commit(%lld): Failed to reserve %lld " - "bytes of RAM\n", this, size, toReserve); + dprintf("%p->VMAnonymousCache::_Commit(%" B_PRIdOFF "): Failed to " + "reserve %" B_PRIdOFF " bytes of RAM\n", this, size, toReserve); return B_NO_MEMORY; } @@ -1370,8 +1370,8 @@ swap_init_post_modules() status_t error = _kern_write_stat(fd, NULL, false, &stat, sizeof(struct stat), B_STAT_SIZE | B_STAT_SIZE_INSECURE); if (error != B_OK) { - dprintf("Failed to resize /var/swap to %lld bytes: %s\n", size, - strerror(error)); + dprintf("Failed to resize /var/swap to %" B_PRIdOFF " bytes: %s\n", + size, strerror(error)); } close(fd); diff --git a/src/system/kernel/vm/VMCache.cpp b/src/system/kernel/vm/VMCache.cpp index b16ecb54c1..c28dcd4406 100644 --- a/src/system/kernel/vm/VMCache.cpp +++ b/src/system/kernel/vm/VMCache.cpp @@ -1328,8 +1328,8 @@ VMCache::Dump(bool showPages) const kprintf(" ref_count: %" B_PRId32 "\n", RefCount()); kprintf(" source: %p\n", source); kprintf(" type: %s\n", vm_cache_type_to_string(type)); - kprintf(" virtual_base: 0x%Lx\n", virtual_base); - kprintf(" virtual_end: 0x%Lx\n", virtual_end); + kprintf(" virtual_base: 0x%" B_PRIx64 "\n", virtual_base); + kprintf(" virtual_end: 0x%" B_PRIx64 "\n", virtual_end); kprintf(" temporary: %" B_PRIu32 "\n", temporary); kprintf(" lock: %p\n", &fLock); #if KDEBUG diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 858985ec12..13073782a4 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3114,7 +3114,7 @@ dump_caches_recursively(VMCache* cache, cache_info& info, int level) kprintf("/%lu", info.page_count); if (cache->type == CACHE_TYPE_RAM || (level == 0 && info.committed > 0)) { - kprintf(", committed: %lld", cache->committed_size); + kprintf(", committed: %" B_PRIdOFF, cache->committed_size); if (level == 0) kprintf("/%lu", info.committed); @@ -3267,7 +3267,7 @@ dump_area_struct(VMArea* area, bool mappings) kprintf("memory_type:\t%#" B_PRIx32 "\n", area->MemoryType()); kprintf("cache:\t\t%p\n", area->cache); kprintf("cache_type:\t%s\n", vm_cache_type_to_string(area->cache_type)); - kprintf("cache_offset:\t0x%Lx\n", area->cache_offset); + kprintf("cache_offset:\t0x%" B_PRIx64 "\n", area->cache_offset); kprintf("cache_next:\t%p\n", area->cache_next); kprintf("cache_prev:\t%p\n", area->cache_prev); From 4f78437c0d5ba6c2904dd0b1f658f9711d397815 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 2 Jul 2012 10:13:37 +0100 Subject: [PATCH 052/273] Style fix. --- src/system/kernel/debug/tracing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/debug/tracing.cpp b/src/system/kernel/debug/tracing.cpp index 04763b8766..ebe90ef0ce 100644 --- a/src/system/kernel/debug/tracing.cpp +++ b/src/system/kernel/debug/tracing.cpp @@ -805,10 +805,10 @@ AbstractTraceEntry::Dump(TraceOutput& out) ? fTime - out.LastEntryTime() : fTime; - if (out.Flags() & TRACE_OUTPUT_TEAM_ID) + if (out.Flags() & TRACE_OUTPUT_TEAM_ID) { out.Print("[%6" B_PRId32 ":%6" B_PRId32 "] %10" B_PRId64 ": ", fThread, fTeam, time); - else + } else out.Print("[%6" B_PRId32 "] %10" B_PRId64 ": ", fThread, time); AddDump(out); From da80a0500c33176998887bcae22828d9e997477f Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 2 Jul 2012 13:50:01 +0100 Subject: [PATCH 053/273] Preparation for merge of x86 and x86_64 kernel sources. Since x86 and x86_64 share a lot of common code, x86_64 kernel sources/headers are going to reside under headers/private/kernel/arch/x86 and src/system/kernel/arch/x86 along with the existing x86 code. This commit changes the build system to handle this. A new variable, TARGET_KERNEL_ARCH, has been added. This is the name of the kernel/boot architecture directory name, set to x86 on both x86 and x86_64. This is now used in all places where TARGET_ARCH was used to get to kernel arch sources/headers (I've changed everything necessary as far as I can tell). Kernel won't build for x86_64 at the moment as the sources have not been merged, loader does. --- build/jam/BuildSetup | 11 ++++-- .../kernel/bluetooth/btCoreData/Jamfile | 2 +- src/add-ons/kernel/bluetooth/hci/Jamfile | 2 +- src/add-ons/kernel/busses/agp_gart/Jamfile | 2 +- src/add-ons/kernel/console/vga_text/Jamfile | 2 +- src/add-ons/kernel/file_cache/Jamfile | 2 +- src/system/boot/Jamfile | 4 +- src/system/boot/arch/arm/Jamfile | 6 +-- src/system/boot/arch/m68k/Jamfile | 10 ++--- src/system/boot/arch/mipsel/Jamfile | 4 +- src/system/boot/arch/ppc/Jamfile | 4 +- src/system/boot/arch/x86/Jamfile | 29 ++++++++------- src/system/boot/arch/x86_64/Jamfile | 37 ------------------- src/system/boot/loader/Jamfile | 17 ++------- src/system/boot/platform/cfe/arch/ppc/Jamfile | 4 +- .../platform/openfirmware/arch/ppc/Jamfile | 4 +- .../boot/platform/raspberrypi_arm/Jamfile | 2 +- src/system/boot/platform/u-boot/Jamfile | 4 +- .../boot/platform/u-boot/arch/arm/Jamfile | 6 +-- .../boot/platform/u-boot/arch/ppc/Jamfile | 6 +-- src/system/kernel/Jamfile | 4 +- src/system/kernel/arch/Jamfile | 2 +- src/system/kernel/arch/arm/Jamfile | 2 +- src/tests/servers/registrar/Jamfile | 2 +- src/tests/system/boot/loader/Jamfile | 2 +- .../system/kernel/disk_device_manager/Jamfile | 2 +- src/tests/system/kernel/scheduler/Jamfile | 2 +- src/tools/gensyscalls/Jamfile | 2 +- 28 files changed, 68 insertions(+), 108 deletions(-) delete mode 100644 src/system/boot/arch/x86_64/Jamfile diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 97856a8aec..1e924f0d75 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -193,7 +193,7 @@ switch $(HAIKU_DISTRO_COMPATIBILITY) { # analyze the gcc machine spec to determine HAIKU_CPU switch $(HAIKU_GCC_MACHINE) { case i?86-* : HAIKU_CPU = x86 ; - case x86_64-* : HAIKU_CPU = x86_64 ; + case x86_64-* : HAIKU_CPU = x86_64 ; case powerpc-* : HAIKU_CPU = ppc ; case m68k-* : HAIKU_CPU = m68k ; case mipsel-* : HAIKU_CPU = mipsel ; @@ -252,11 +252,15 @@ switch $(HAIKU_CPU) { } case x86_64 : { + # x86_64 completely shares the x86 bootloader. HAIKU_BOOT_PLATFORM = bios_ia32 ; HAIKU_BOOT_FLOPPY_IMAGE_SIZE = 2880 ; # in kB # offset in floppy image (>= sizeof(haiku_loader)) HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET = 300 ; # in kB + # x86_64 kernel source is under arch/x86. + HAIKU_KERNEL_ARCH = x86 ; + # yasm is required for target arch x86_64 if ! $(HAIKU_YASM) { Exit "HAIKU_YASM not set. Please re-run configure." ; @@ -306,6 +310,7 @@ HAIKU_ARCH ?= $(HAIKU_CPU) ; HAIKU_ARCH_MACRO_DEFINE = ARCH_$(HAIKU_ARCH) ; HAIKU_DEFINES += $(HAIKU_ARCH_MACRO_DEFINE) ; HAIKU_DEFINES += BOOT_ARCHIVE_IMAGE_OFFSET=$(HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET) ; +HAIKU_KERNEL_ARCH ?= $(HAIKU_ARCH) ; HAIKU_ATA_STACK ?= 1 ; # directories @@ -457,7 +462,7 @@ HAIKU_PRIVATE_SYSTEM_HEADERS = HAIKU_PRIVATE_KERNEL_HEADERS = [ PrivateHeaders $(DOT) kernel libroot shared kernel/boot/platform/$(HAIKU_BOOT_PLATFORM) ] - [ ArchHeaders $(HAIKU_ARCH) ] + [ ArchHeaders $(HAIKU_KERNEL_ARCH) ] [ FDirName $(HAIKU_COMMON_DEBUG_OBJECT_DIR) system kernel ] $(HAIKU_PRIVATE_SYSTEM_HEADERS) ; @@ -968,7 +973,7 @@ if $(TARGET_PLATFORM) != haiku { # specified TARGET_PLATFORM. local buildVars = - ARCH CPU GCC_VERSION + ARCH CPU GCC_VERSION KERNEL_ARCH AR CC C++ LD OBJCOPY RANLIB diff --git a/src/add-ons/kernel/bluetooth/btCoreData/Jamfile b/src/add-ons/kernel/bluetooth/btCoreData/Jamfile index c5ea92268b..a0f577eb33 100644 --- a/src/add-ons/kernel/bluetooth/btCoreData/Jamfile +++ b/src/add-ons/kernel/bluetooth/btCoreData/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel bluetooth btCoreData ; UsePrivateHeaders kernel net bluetooth ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; # disable debug output, if debugging is disabled diff --git a/src/add-ons/kernel/bluetooth/hci/Jamfile b/src/add-ons/kernel/bluetooth/hci/Jamfile index 5cf637f091..4a3020cb20 100644 --- a/src/add-ons/kernel/bluetooth/hci/Jamfile +++ b/src/add-ons/kernel/bluetooth/hci/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel bluetooth hci ; UsePrivateKernelHeaders ; UsePrivateHeaders net bluetooth ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; # disable debug output, if debugging is disabled diff --git a/src/add-ons/kernel/busses/agp_gart/Jamfile b/src/add-ons/kernel/busses/agp_gart/Jamfile index e7078ce150..c0177357ef 100644 --- a/src/add-ons/kernel/busses/agp_gart/Jamfile +++ b/src/add-ons/kernel/busses/agp_gart/Jamfile @@ -3,7 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel busses agp_gart ; SetSubDirSupportedPlatformsBeOSCompatible ; SubDirC++Flags -fno-rtti ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName graphics intel_extreme ] ; UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders drivers graphics kernel ; diff --git a/src/add-ons/kernel/console/vga_text/Jamfile b/src/add-ons/kernel/console/vga_text/Jamfile index 4e697e891a..8deb5694a4 100644 --- a/src/add-ons/kernel/console/vga_text/Jamfile +++ b/src/add-ons/kernel/console/vga_text/Jamfile @@ -1,6 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel console vga_text ; -UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; KernelAddon vga_text : diff --git a/src/add-ons/kernel/file_cache/Jamfile b/src/add-ons/kernel/file_cache/Jamfile index 02ccf99341..6d83c5a6d0 100644 --- a/src/add-ons/kernel/file_cache/Jamfile +++ b/src/add-ons/kernel/file_cache/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel file_cache ; UsePrivateKernelHeaders ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; KernelAddon log : diff --git a/src/system/boot/Jamfile b/src/system/boot/Jamfile index 548883adb4..a5f5a6906e 100644 --- a/src/system/boot/Jamfile +++ b/src/system/boot/Jamfile @@ -43,7 +43,7 @@ AddResources haiku_loader : boot_loader.rdef ; BootLd boot_loader_$(TARGET_BOOT_PLATFORM) : boot_platform_$(TARGET_BOOT_PLATFORM).o - boot_arch_$(TARGET_ARCH).o + boot_arch_$(TARGET_KERNEL_ARCH).o boot_loader.a boot_net.a boot_partitions.a @@ -109,6 +109,6 @@ BuildBiosLoader haiku_loader : boot_loader_$(TARGET_BOOT_PLATFORM) ; # different target for PXE, to be build with TARGET_BOOT_PLATFORM=pxe_ia32 jam pxehaiku-loader BuildBiosLoader pxehaiku-loader : boot_loader_$(TARGET_BOOT_PLATFORM) ; -SubInclude HAIKU_TOP src system boot arch $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src system boot arch $(TARGET_KERNEL_ARCH) ; SubInclude HAIKU_TOP src system boot loader ; SubInclude HAIKU_TOP src system boot platform ; diff --git a/src/system/boot/arch/arm/Jamfile b/src/system/boot/arch/arm/Jamfile index d035c41a1f..7460d4dd95 100644 --- a/src/system/boot/arch/arm/Jamfile +++ b/src/system/boot/arch/arm/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src system boot arch arm ; #XXX: should not be needed here -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; { local defines = _BOOT_MODE ; @@ -22,7 +22,7 @@ local kernelLibArchObjects = memset.o ; -BootMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : debug_uart_8250.cpp arch_uart_8250.cpp arch_uart_pl011.cpp @@ -38,7 +38,7 @@ BootMergeObject boot_arch_$(TARGET_ARCH).o : ; SEARCH on [ FGristFiles arch_elf.cpp uart.cpp arch_uart_8250.cpp arch_uart_pl011.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; SEARCH on [ FGristFiles debug_uart_8250.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ; diff --git a/src/system/boot/arch/m68k/Jamfile b/src/system/boot/arch/m68k/Jamfile index 349a350722..26e9d2ad52 100644 --- a/src/system/boot/arch/m68k/Jamfile +++ b/src/system/boot/arch/m68k/Jamfile @@ -13,7 +13,7 @@ local kernelLibArchObjects = memset.o ; -BootMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : arch_elf.cpp $(librootArchObjects) : -fno-pic @@ -21,23 +21,23 @@ BootMergeObject boot_arch_$(TARGET_ARCH).o : $(kernelLibArchObjects) ; -BootMergeObject boot_arch_$(TARGET_ARCH)_030.o : +BootMergeObject boot_arch_m68k_030.o : mmu_030.cpp : -fno-pic -Wno-unused -m68030 ; -BootMergeObject boot_arch_$(TARGET_ARCH)_040.o : +BootMergeObject boot_arch_m68k_040.o : mmu_040.cpp : -fno-pic -Wno-unused -m68040 ; -BootMergeObject boot_arch_$(TARGET_ARCH)_060.o : +BootMergeObject boot_arch_m68k_060.o : mmu_060.cpp : -fno-pic -Wno-unused -m68060 ; SEARCH on [ FGristFiles arch_elf.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; SEARCH on [ FGristFiles $(librootArchObjects) ] = [ FDirName $(HAIKU_TOP) src system libroot posix string arch $(TARGET_ARCH) ] ; diff --git a/src/system/boot/arch/mipsel/Jamfile b/src/system/boot/arch/mipsel/Jamfile index 33f0198b1d..aafa31d30a 100644 --- a/src/system/boot/arch/mipsel/Jamfile +++ b/src/system/boot/arch/mipsel/Jamfile @@ -8,7 +8,7 @@ local kernelLibArchObjects = memset.o ; -BootMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : arch_elf.cpp : # additional flags : @@ -17,5 +17,5 @@ BootMergeObject boot_arch_$(TARGET_ARCH).o : ; SEARCH on [ FGristFiles arch_elf.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; diff --git a/src/system/boot/arch/ppc/Jamfile b/src/system/boot/arch/ppc/Jamfile index 07ad229e62..ea1c5a600a 100644 --- a/src/system/boot/arch/ppc/Jamfile +++ b/src/system/boot/arch/ppc/Jamfile @@ -15,7 +15,7 @@ local kernelLibArchObjects = memset.o ; -BootMergeObject boot_arch_$(TARGET_ARCH).o : +BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : debug_uart_8250.cpp arch_uart_8250.cpp arch_elf.cpp @@ -26,7 +26,7 @@ BootMergeObject boot_arch_$(TARGET_ARCH).o : ; SEARCH on [ FGristFiles arch_elf.cpp arch_uart_8250.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; SEARCH on [ FGristFiles debug_uart_8250.cpp ] = [ FDirName $(HAIKU_TOP) src system kernel arch generic ] ; diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index e7cff1e494..1ef6a979c5 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -2,33 +2,36 @@ SubDir HAIKU_TOP src system boot arch x86 ; DEFINES += _BOOT_MODE ; -local kernelArchSources = - arch_elf.cpp +local bootArchSources = + arch_elf64.cpp ; -local kernelArchObjects = - cpuid.o +local kernelArchSources = + arch_elf.cpp + cpuid.S ; local kernelLibArchSources = arch_string.S ; -local kernelLibArchObjects = - byteorder.o +local librootOsArchSources = + byteorder.S ; -BootMergeObject boot_arch_$(TARGET_ARCH).o : - arch_elf64.cpp +BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : + $(bootArchSources) $(kernelArchSources) $(kernelLibArchSources) + $(librootOsArchSources) : # additional flags - : - $(kernelArchObjects) - $(kernelLibArchObjects) ; +SEARCH on [ FGristFiles $(bootArchSources) ] + = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; SEARCH on [ FGristFiles $(kernelArchSources) ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; SEARCH on [ FGristFiles $(kernelLibArchSources) ] - = [ FDirName $(HAIKU_TOP) src system kernel lib arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; +SEARCH on [ FGristFiles $(librootOsArchSources) ] + = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; diff --git a/src/system/boot/arch/x86_64/Jamfile b/src/system/boot/arch/x86_64/Jamfile deleted file mode 100644 index f81c3f1b41..0000000000 --- a/src/system/boot/arch/x86_64/Jamfile +++ /dev/null @@ -1,37 +0,0 @@ -SubDir HAIKU_TOP src system boot arch x86_64 ; - -DEFINES += _BOOT_MODE ; - -local bootArchSources = - arch_elf64.cpp -; - -local kernelArchSources = - arch_elf.cpp - cpuid.S -; - -local kernelLibArchSources = - arch_string.S -; - -local librootOsArchSources = - byteorder.S -; - -BootMergeObject boot_arch_$(TARGET_ARCH).o : - $(bootArchSources) - $(kernelArchSources) - $(kernelLibArchSources) - $(librootOsArchSources) - : # additional flags -; - -SEARCH on [ FGristFiles $(bootArchSources) ] - = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; -SEARCH on [ FGristFiles $(kernelArchSources) ] - = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; -SEARCH on [ FGristFiles $(kernelLibArchSources) ] - = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; -SEARCH on [ FGristFiles $(librootOsArchSources) ] - = [ FDirName $(HAIKU_TOP) src system libroot os arch x86 ] ; diff --git a/src/system/boot/loader/Jamfile b/src/system/boot/loader/Jamfile index f325c3279f..089f0dedea 100644 --- a/src/system/boot/loader/Jamfile +++ b/src/system/boot/loader/Jamfile @@ -12,7 +12,7 @@ UsePrivateHeaders shared storage ; { local defines = _BOOT_MODE - BOOT_ARCH=\\\"$(TARGET_ARCH)\\\" + BOOT_ARCH=\\\"$(TARGET_KERNEL_ARCH)\\\" KMESSAGE_CONTAINER_ONLY BOOT_SUPPORT_PARTITION_INTEL @@ -25,7 +25,7 @@ UsePrivateHeaders shared storage ; # Add architecture specific partition/file system modules - switch $(TARGET_ARCH) { + switch $(TARGET_KERNEL_ARCH) { case "ppc" : { defines += @@ -43,17 +43,6 @@ UsePrivateHeaders shared storage ; BOOT_SUPPORT_PARTITION_EFI - #BOOT_SUPPORT_FILE_SYSTEM_FAT - ; - } - case "x86_64" : - { - defines += - ALTERNATE_BOOT_ARCH=\\\"x86\\\" - BOOT_SUPPORT_ELF64 - - BOOT_SUPPORT_PARTITION_EFI - #BOOT_SUPPORT_FILE_SYSTEM_FAT ; } @@ -132,7 +121,7 @@ SEARCH on [ FGristFiles intel.cpp PartitionMap.cpp PartitionMapParser.cpp ] = [ FDirName $(HAIKU_TOP) src add-ons kernel partitioning_systems intel ] ; SEARCH on [ FGristFiles stage2_crt0.S ] - = [ FDirName $(HAIKU_TOP) src system boot arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system boot arch $(TARGET_KERNEL_ARCH) ] ; SubInclude HAIKU_TOP src system boot loader file_systems ; diff --git a/src/system/boot/platform/cfe/arch/ppc/Jamfile b/src/system/boot/platform/cfe/arch/ppc/Jamfile index f7408331d2..5bace2e838 100644 --- a/src/system/boot/platform/cfe/arch/ppc/Jamfile +++ b/src/system/boot/platform/cfe/arch/ppc/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src system boot platform cfe arch ppc ; SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ; UsePrivateSystemHeaders ; -UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; SubDirC++Flags -fno-rtti ; @@ -16,4 +16,4 @@ BootStaticLibrary boot_platform_cfe_ppc : ; SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; diff --git a/src/system/boot/platform/openfirmware/arch/ppc/Jamfile b/src/system/boot/platform/openfirmware/arch/ppc/Jamfile index a82fda7594..cb053f478f 100644 --- a/src/system/boot/platform/openfirmware/arch/ppc/Jamfile +++ b/src/system/boot/platform/openfirmware/arch/ppc/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src system boot platform openfirmware arch ppc ; SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ; UsePrivateSystemHeaders ; -UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; SubDirC++Flags -fno-rtti ; @@ -16,4 +16,4 @@ BootStaticLibrary boot_platform_openfirmware_ppc : ; SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; diff --git a/src/system/boot/platform/raspberrypi_arm/Jamfile b/src/system/boot/platform/raspberrypi_arm/Jamfile index 9b4b72ef39..7e35fb96f8 100644 --- a/src/system/boot/platform/raspberrypi_arm/Jamfile +++ b/src/system/boot/platform/raspberrypi_arm/Jamfile @@ -7,7 +7,7 @@ UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName graphics vesa ] ; UsePrivateHeaders [ FDirName storage ] ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; { local defines = _BOOT_MODE ; diff --git a/src/system/boot/platform/u-boot/Jamfile b/src/system/boot/platform/u-boot/Jamfile index 7d9ba932f0..84d3abfbc3 100644 --- a/src/system/boot/platform/u-boot/Jamfile +++ b/src/system/boot/platform/u-boot/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src system boot platform u-boot ; SubDirHdrs $(HAIKU_TOP) headers private kernel boot platform $(TARGET_BOOT_PLATFORM) ; -SubDirHdrs $(HAIKU_TOP) src system boot arch $(TARGET_ARCH) ; +SubDirHdrs $(HAIKU_TOP) src system boot arch $(TARGET_KERNEL_ARCH) ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName graphics common ] ; @@ -12,7 +12,7 @@ UsePrivateHeaders [ FDirName kernel arch generic ] ; # TODO: move this to arch/arm ! -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; { local defines = _BOOT_MODE ; diff --git a/src/system/boot/platform/u-boot/arch/arm/Jamfile b/src/system/boot/platform/u-boot/arch/arm/Jamfile index fdfbaa96c0..cd48629133 100644 --- a/src/system/boot/platform/u-boot/arch/arm/Jamfile +++ b/src/system/boot/platform/u-boot/arch/arm/Jamfile @@ -2,9 +2,9 @@ SubDir HAIKU_TOP src system boot platform u-boot arch arm ; SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ; UsePrivateSystemHeaders ; -UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; SubDirC++Flags -fno-rtti ; @@ -21,4 +21,4 @@ BootMergeObject boot_platform_u-boot_arm.o : ; #SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ] -# = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; +# = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; diff --git a/src/system/boot/platform/u-boot/arch/ppc/Jamfile b/src/system/boot/platform/u-boot/arch/ppc/Jamfile index 4694565b7e..c24f3f80f2 100644 --- a/src/system/boot/platform/u-boot/arch/ppc/Jamfile +++ b/src/system/boot/platform/u-boot/arch/ppc/Jamfile @@ -2,9 +2,9 @@ SubDir HAIKU_TOP src system boot platform u-boot arch ppc ; SubDirHdrs $(HAIKU_TOP) src system boot platform $(TARGET_BOOT_PLATFORM) ; UsePrivateSystemHeaders ; -UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ] +UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] [ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; SubDirC++Flags -fno-rtti ; @@ -21,4 +21,4 @@ BootMergeObject boot_platform_u-boot_ppc.o : ; SEARCH on [ FGristFiles arch_cpu_asm.S arch_mmu.cpp ] - = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ; + = [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_KERNEL_ARCH) ] ; diff --git a/src/system/kernel/Jamfile b/src/system/kernel/Jamfile index 04b3719298..d40862b7e9 100644 --- a/src/system/kernel/Jamfile +++ b/src/system/kernel/Jamfile @@ -114,7 +114,7 @@ KernelLd kernel_$(TARGET_ARCH) : kernel_util.o kernel_vm.o - kernel_arch_$(TARGET_ARCH).o + kernel_arch_$(TARGET_KERNEL_ARCH).o kernel_platform_$(TARGET_BOOT_PLATFORM).o linkhack.so @@ -147,7 +147,7 @@ KernelLd kernel.so : kernel_util.o kernel_vm.o - kernel_arch_$(TARGET_ARCH).o + kernel_arch_$(TARGET_KERNEL_ARCH).o kernel_platform_$(TARGET_BOOT_PLATFORM).o linkhack.so diff --git a/src/system/kernel/arch/Jamfile b/src/system/kernel/arch/Jamfile index f93fb20fd0..9a7dbb5696 100644 --- a/src/system/kernel/arch/Jamfile +++ b/src/system/kernel/arch/Jamfile @@ -1,3 +1,3 @@ SubDir HAIKU_TOP src system kernel arch ; -SubInclude HAIKU_TOP src system kernel arch $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src system kernel arch $(TARGET_KERNEL_ARCH) ; diff --git a/src/system/kernel/arch/arm/Jamfile b/src/system/kernel/arch/arm/Jamfile index 13a56e44e6..f95ef0fe32 100644 --- a/src/system/kernel/arch/arm/Jamfile +++ b/src/system/kernel/arch/arm/Jamfile @@ -2,7 +2,7 @@ SubDir HAIKU_TOP src system kernel arch arm ; SubDirHdrs $(SUBDIR) $(DOTDOT) generic ; UsePrivateKernelHeaders ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) board $(TARGET_BOOT_BOARD) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) board $(TARGET_BOOT_BOARD) ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) paging ] ; diff --git a/src/tests/servers/registrar/Jamfile b/src/tests/servers/registrar/Jamfile index 5a3cf21962..925515292e 100644 --- a/src/tests/servers/registrar/Jamfile +++ b/src/tests/servers/registrar/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src tests servers registrar ; UsePublicHeaders [ FDirName add-ons registrar ] ; -UseArchHeaders $(TARGET_ARCH) ; +UseArchHeaders $(TARGET_KERNEL_ARCH) ; # some test programs diff --git a/src/tests/system/boot/loader/Jamfile b/src/tests/system/boot/loader/Jamfile index 3378873b0d..aec23cc9e7 100644 --- a/src/tests/system/boot/loader/Jamfile +++ b/src/tests/system/boot/loader/Jamfile @@ -5,7 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; UsePrivateHeaders [ FDirName kernel util ] ; UsePrivateHeaders kernel shared storage system ; -SubDirSysHdrs $(HAIKU_TOP) headers private kernel arch $(TARGET_ARCH) ; +SubDirSysHdrs $(HAIKU_TOP) headers private kernel arch $(TARGET_KERNEL_ARCH) ; SubDirSysHdrs $(HAIKU_TOP) headers private system arch $(TARGET_ARCH) ; SubDirSysHdrs $(HAIKU_TOP) src tests system boot loader ; SubDirHdrs $(HAIKU_TOP) src system boot loader ; diff --git a/src/tests/system/kernel/disk_device_manager/Jamfile b/src/tests/system/kernel/disk_device_manager/Jamfile index c25c21da12..e73a79f47f 100644 --- a/src/tests/system/kernel/disk_device_manager/Jamfile +++ b/src/tests/system/kernel/disk_device_manager/Jamfile @@ -10,7 +10,7 @@ SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits storage ] ; UsePrivateHeaders shared ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; UsePrivateHeaders [ FDirName kernel disk_device_manager ] ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName kernel fs ] ; UsePrivateHeaders [ FDirName kernel ] ; UsePrivateHeaders [ FDirName kernel util ] ; diff --git a/src/tests/system/kernel/scheduler/Jamfile b/src/tests/system/kernel/scheduler/Jamfile index c7c4dcf295..b90549924c 100644 --- a/src/tests/system/kernel/scheduler/Jamfile +++ b/src/tests/system/kernel/scheduler/Jamfile @@ -3,7 +3,7 @@ SubDir HAIKU_TOP src tests system kernel scheduler ; #SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src system kernel util ] ; UsePrivateHeaders kernel ; -UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; +UsePrivateHeaders [ FDirName kernel arch $(TARGET_KERNEL_ARCH) ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; #UseHeaders [ FDirName $(HAIKU_TOP) src system kernel cache ] ; diff --git a/src/tools/gensyscalls/Jamfile b/src/tools/gensyscalls/Jamfile index 02dbeb495b..156b9d78e3 100644 --- a/src/tools/gensyscalls/Jamfile +++ b/src/tools/gensyscalls/Jamfile @@ -42,7 +42,7 @@ rule PreprocessSyscalls local headers = [ on $(1) return $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ; local sysHeaders = $(TARGET_PRIVATE_SYSTEM_HEADERS) - [ ArchHeaders $(TARGET_ARCH) ] + [ ArchHeaders $(TARGET_KERNEL_ARCH) ] [ on $(1) return $(SUBDIRSYSHDRS) $(SYSHDRS) ] $(HAIKU_HDRS) ; From 0897e314b79d09b04349d3cfe6093a3fd6220da1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 2 Jul 2012 18:47:06 +0100 Subject: [PATCH 054/273] Merged x86_64 headers into x86 headers. Not many changes seeing as there's not much x86_64 stuff done yet. Small differences are handled with ifdefs, large differences (descriptors.h, struct iframe) have separate headers under arch/x86/32 and arch/x86/64. --- headers/private/kernel/arch/common_x86/cpu.h | 294 -------------- .../private/kernel/arch/x86/32/descriptors.h | 140 +++++++ headers/private/kernel/arch/x86/32/iframe.h | 76 ++++ .../private/kernel/arch/x86/64/descriptors.h | 169 ++++++++ headers/private/kernel/arch/x86/64/iframe.h | 40 ++ headers/private/kernel/arch/x86/arch_cpu.h | 369 ++++++++++++++---- headers/private/kernel/arch/x86/arch_int.h | 19 +- headers/private/kernel/arch/x86/arch_kernel.h | 49 ++- headers/private/kernel/arch/x86/arch_thread.h | 48 ++- .../kernel/arch/x86/arch_thread_types.h | 16 +- headers/private/kernel/arch/x86/descriptors.h | 111 +----- src/system/boot/platform/bios_ia32/long.cpp | 6 +- 12 files changed, 830 insertions(+), 507 deletions(-) delete mode 100644 headers/private/kernel/arch/common_x86/cpu.h create mode 100644 headers/private/kernel/arch/x86/32/descriptors.h create mode 100644 headers/private/kernel/arch/x86/32/iframe.h create mode 100644 headers/private/kernel/arch/x86/64/descriptors.h create mode 100644 headers/private/kernel/arch/x86/64/iframe.h diff --git a/headers/private/kernel/arch/common_x86/cpu.h b/headers/private/kernel/arch/common_x86/cpu.h deleted file mode 100644 index f825d13567..0000000000 --- a/headers/private/kernel/arch/common_x86/cpu.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. - * Distributed under the terms of the MIT License. - * - * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ -#ifndef _KERNEL_ARCH_COMMON_X86_CPU_H -#define _KERNEL_ARCH_COMMON_X86_CPU_H - - -#ifndef _ASSEMBLER -#include -#endif - - -#undef PAUSE -#define PAUSE() asm volatile ("pause;") - - -// MSR registers (possibly Intel specific) -#define IA32_MSR_TSC 0x10 -#define IA32_MSR_APIC_BASE 0x1b - -#define IA32_MSR_MTRR_CAPABILITIES 0xfe -#define IA32_MSR_SYSENTER_CS 0x174 -#define IA32_MSR_SYSENTER_ESP 0x175 -#define IA32_MSR_SYSENTER_EIP 0x176 -#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff -#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 -#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 - -// K8 MSR registers -#define K8_MSR_IPM 0xc0010055 - -// x86 features from cpuid eax 1, edx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) -#define IA32_FEATURE_FPU (1 << 0) // x87 fpu -#define IA32_FEATURE_VME (1 << 1) // virtual 8086 -#define IA32_FEATURE_DE (1 << 2) // debugging extensions -#define IA32_FEATURE_PSE (1 << 3) // page size extensions -#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction -#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction -#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing -#define IA32_FEATURE_MCE (1 << 7) // machine check exception -#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction -#define IA32_FEATURE_APIC (1 << 9) // local apic on chip -// (1 << 10) // Reserved -#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT -#define IA32_FEATURE_MTRR (1 << 12) // MTRR -#define IA32_FEATURE_PGE (1 << 13) // paging global bit -#define IA32_FEATURE_MCA (1 << 14) // machine check architecture -#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction -#define IA32_FEATURE_PAT (1 << 16) // page attribute table -#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages -#define IA32_FEATURE_PSN (1 << 18) // processor serial number -#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction -// (1 << 20) // Reserved -#define IA32_FEATURE_DS (1 << 21) // debug store -#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl -#define IA32_FEATURE_MMX (1 << 23) // mmx instructions -#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction -#define IA32_FEATURE_SSE (1 << 25) // SSE -#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 -#define IA32_FEATURE_SS (1 << 27) // self snoop -#define IA32_FEATURE_HTT (1 << 28) // hyperthreading -#define IA32_FEATURE_TM (1 << 29) // thermal monitor -#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 -#define IA32_FEATURE_PBE (1 << 31) // pending break enable - -// x86 features from cpuid eax 1, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) -#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 -#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction -#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store -#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT -#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store -#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions -#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions -#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep -#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 -#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 -#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID -// (1 << 11) // Reserved -#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add -#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B -#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control -#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability -// (1 << 16) // Reserved -#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers -#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access -#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 -#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 -#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support -#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction -#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction -#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline -#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions -#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States -#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE -#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions -#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion -#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction -#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor - -// x86 features from cpuid eax 0x80000001, edx register (AMD) -// only care about the ones that are unique to this register -#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET -#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit -#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions -#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR -#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction -#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode -#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions -#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! - -// x86 defined features from cpuid eax 6, eax register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor -#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology -#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer -#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification -#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty -#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management - -// x86 defined features from cpuid eax 6, ecx register -// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) -#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF -#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS - -// cr4 flags -#define IA32_CR4_PAE (1UL << 5) -#define IA32_CR4_GLOBAL_PAGES (1UL << 7) - -// Memory type ranges -#define IA32_MTR_UNCACHED 0 -#define IA32_MTR_WRITE_COMBINING 1 -#define IA32_MTR_WRITE_THROUGH 4 -#define IA32_MTR_WRITE_PROTECTED 5 -#define IA32_MTR_WRITE_BACK 6 - -// EFLAGS register -#define X86_EFLAGS_CARRY 0x00000001 -#define X86_EFLAGS_RESERVED1 0x00000002 -#define X86_EFLAGS_PARITY 0x00000004 -#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 -#define X86_EFLAGS_ZERO 0x00000040 -#define X86_EFLAGS_SIGN 0x00000080 -#define X86_EFLAGS_TRAP 0x00000100 -#define X86_EFLAGS_INTERRUPT 0x00000200 -#define X86_EFLAGS_DIRECTION 0x00000400 -#define X86_EFLAGS_OVERFLOW 0x00000800 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 -#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 -#define X86_EFLAGS_NESTED_TASK 0x00004000 -#define X86_EFLAGS_RESUME 0x00010000 -#define X86_EFLAGS_V86_MODE 0x00020000 -#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 -#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 -#define X86_EFLAGS_ID 0x00200000 - -#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ - | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ - | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) - - -#ifndef _ASSEMBLER - - -typedef struct x86_mtrr_info { - uint64 base; - uint64 size; - uint8 type; -} x86_mtrr_info; - -typedef struct x86_optimized_functions { - void (*memcpy)(void* dest, const void* source, size_t count); - void* memcpy_end; - void (*memset)(void* dest, int value, size_t count); - void* memset_end; -} x86_optimized_functions; - -typedef struct x86_cpu_module_info { - module_info info; - uint32 (*count_mtrrs)(void); - void (*init_mtrrs)(void); - - void (*set_mtrr)(uint32 index, uint64 base, uint64 length, - uint8 type); - status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, - uint8* _type); - void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, - uint32 count); - - void (*get_optimized_functions)(x86_optimized_functions* functions); -} x86_cpu_module_info; - -// features -enum x86_feature_type { - FEATURE_COMMON = 0, // cpuid eax=1, ecx register - FEATURE_EXT, // cpuid eax=1, edx register - FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) - FEATURE_6_EAX, // cpuid eax=6, eax registers - FEATURE_6_ECX, // cpuid eax=6, ecx registers - - FEATURE_NUM -}; - -enum x86_vendors { - VENDOR_INTEL = 0, - VENDOR_AMD, - VENDOR_CYRIX, - VENDOR_UMC, - VENDOR_NEXGEN, - VENDOR_CENTAUR, - VENDOR_RISE, - VENDOR_TRANSMETA, - VENDOR_NSC, - - VENDOR_NUM, - VENDOR_UNKNOWN, -}; - - -#define nop() __asm__ ("nop"::) - -#define read_cr2(value) \ - __asm__("mov %%cr2,%0" : "=r" (value)) - -#define read_cr3(value) \ - __asm__("mov %%cr3,%0" : "=r" (value)) - -#define write_cr3(value) \ - __asm__("mov %0,%%cr3" : : "r" (value)) - -#define read_dr3(value) \ - __asm__("mov %%dr3,%0" : "=r" (value)) - -#define write_dr3(value) \ - __asm__("mov %0,%%dr3" : : "r" (value)) - -#define invalidate_TLB(va) \ - __asm__("invlpg (%0)" : : "r" (va)) - -#define wbinvd() \ - __asm__("wbinvd") - -#define out8(value,port) \ - __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) - -#define out16(value,port) \ - __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) - -#define out32(value,port) \ - __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) - -#define in8(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in16(port) ({ \ - uint16 _v; \ - __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define in32(port) ({ \ - uint32 _v; \ - __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ - _v; \ -}) - -#define out8_p(value,port) \ - __asm__ ("outb %%al,%%dx\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : : "a" (value), "d" (port)) - -#define in8_p(port) ({ \ - uint8 _v; \ - __asm__ volatile ("inb %%dx,%%al\n" \ - "\tjmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:" : "=a" (_v) : "d" (port)); \ - _v; \ -}) - - -#endif // !_ASSEMBLER - -#endif /* _KERNEL_ARCH_COMMON_X86_CPU_H */ diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h new file mode 100644 index 0000000000..d57bf05da5 --- /dev/null +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -0,0 +1,140 @@ +/* + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_X86_32_DESCRIPTORS_H +#define _KERNEL_ARCH_X86_32_DESCRIPTORS_H + + +#define KERNEL_CODE_SEG 0x8 +#define KERNEL_DATA_SEG 0x10 + +#define USER_CODE_SEG 0x1b +#define USER_DATA_SEG 0x23 + +#define APM_CODE32_SEGMENT 0x28 +#define APM_CODE16_SEGMENT 0x30 +#define APM_DATA_SEGMENT 0x38 + +#define BIOS_DATA_SEGMENT 0x40 + +#ifndef _ASSEMBLER + // this file can also be included from assembler as well + // (and is in arch_interrupts.S) + +#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 +#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) + + +// defines entries in the GDT/LDT + +typedef struct segment_descriptor { + uint16 limit_00_15; // bit 0 - 15 + uint16 base_00_15; // 16 - 31 + uint32 base_23_16 : 8; // 0 - 7 + uint32 type : 4; // 8 - 11 + uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) + uint32 privilege_level : 2; // 13 - 14 + uint32 present : 1; // 15 + uint32 limit_19_16 : 4; // 16 - 19 + uint32 available : 1; // 20 + uint32 zero : 1; // 21 + uint32 d_b : 1; // 22 + uint32 granularity : 1; // 23 + uint32 base_31_24 : 8; // 24 - 31 +} segment_descriptor; + +struct tss { + uint16 prev_task; + uint16 unused0; + uint32 sp0; + uint32 ss0; + uint32 sp1; + uint32 ss1; + uint32 sp2; + uint32 ss2; + uint32 cr3; + uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; + uint32 es, cs, ss, ds, fs, gs; + uint32 ldt_seg_selector; + uint16 unused1; + uint16 io_map_base; +}; + + +static inline void +clear_segment_descriptor(struct segment_descriptor *desc) +{ + *(long long *)desc = 0; +} + + +static inline void +set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) +{ + desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long + desc->base_23_16 = ((addr_t)base >> 16) & 0xff; + desc->base_31_24 = ((addr_t)base >> 24) & 0xff; +} + + +static inline void +set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, + uint8 type, uint8 privilegeLevel) +{ + set_segment_descriptor_base(desc, base); + + // limit is 20 bits long + if (limit & 0xfff00000) { + desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; + desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; + desc->granularity = 1; // 4 KB granularity + } else { + desc->limit_00_15 = (addr_t)limit & 0x0ffff; + desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; + desc->granularity = 0; // 1 byte granularity + } + limit >>= 12; + + + desc->type = type; + desc->desc_type = DT_CODE_DATA_SEGMENT; + desc->privilege_level = privilegeLevel; + + desc->present = 1; + desc->available = 0; // system available bit is currently not used + desc->d_b = 1; // 32-bit code + + desc->zero = 0; +} + + +static inline void +set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) +{ + // the TSS descriptor has a special layout different from the standard descriptor + set_segment_descriptor_base(desc, base); + + desc->limit_00_15 = (addr_t)limit & 0x0ffff; + desc->limit_19_16 = 0; + + desc->type = DT_TSS; + desc->desc_type = DT_SYSTEM_SEGMENT; + desc->privilege_level = DPL_KERNEL; + + desc->present = 1; + desc->granularity = 0; // 1 Byte granularity + desc->available = 0; // system available bit is currently not used + desc->d_b = 0; + + desc->zero = 0; +} + +#endif /* _ASSEMBLER */ + +#endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ diff --git a/headers/private/kernel/arch/x86/32/iframe.h b/headers/private/kernel/arch/x86/32/iframe.h new file mode 100644 index 0000000000..6da6c1f9b2 --- /dev/null +++ b/headers/private/kernel/arch/x86/32/iframe.h @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_X86_32_IFRAME_H +#define _KERNEL_ARCH_X86_32_IFRAME_H + + +struct iframe { + uint32 type; // iframe type + uint32 gs; + uint32 fs; + uint32 es; + uint32 ds; + uint32 edi; + uint32 esi; + uint32 ebp; + uint32 esp; + uint32 ebx; + uint32 edx; + uint32 ecx; + uint32 eax; + uint32 orig_eax; + uint32 orig_edx; + uint32 vector; + uint32 error_code; + uint32 eip; + uint32 cs; + uint32 flags; + + // user_esp and user_ss are only present when the iframe is a userland + // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. + uint32 user_esp; + uint32 user_ss; +}; + +struct vm86_iframe { + uint32 type; // iframe type + uint32 __null_gs; + uint32 __null_fs; + uint32 __null_es; + uint32 __null_ds; + uint32 edi; + uint32 esi; + uint32 ebp; + uint32 __kern_esp; + uint32 ebx; + uint32 edx; + uint32 ecx; + uint32 eax; + uint32 orig_eax; + uint32 orig_edx; + uint32 vector; + uint32 error_code; + uint32 eip; + uint16 cs, __csh; + uint32 flags; + uint32 esp; + uint16 ss, __ssh; + + /* vm86 mode specific part */ + uint16 es, __esh; + uint16 ds, __dsh; + uint16 fs, __fsh; + uint16 gs, __gsh; +}; + +#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ + || ((f)->flags & 0x20000) != 0) +#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) + + +#endif /* _KERNEL_ARCH_X86_32_IFRAME_H */ diff --git a/headers/private/kernel/arch/x86/64/descriptors.h b/headers/private/kernel/arch/x86/64/descriptors.h new file mode 100644 index 0000000000..7e5efb9c83 --- /dev/null +++ b/headers/private/kernel/arch/x86/64/descriptors.h @@ -0,0 +1,169 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H +#define _KERNEL_ARCH_X86_64_DESCRIPTORS_H + + +// Segment definitions. +// Note that the ordering of these is important to SYSCALL/SYSRET. +#define KERNEL_CODE_SEG 0x08 +#define KERNEL_DATA_SEG 0x10 +#define USER_DATA_SEG 0x1b +#define USER_CODE_SEG 0x23 + + +#ifndef _ASSEMBLER + + +#define TSS_BASE_SEGMENT 5 +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) + + +// Structure of a segment descriptor. +struct segment_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 long_mode : 1; + uint32 d_b : 1; + uint32 granularity : 1; + uint32 base1 : 8; +} _PACKED; + +// Structure of a TSS segment descriptor. +struct tss_descriptor { + uint32 limit0 : 16; + uint32 base0 : 24; + uint32 type : 4; + uint32 desc_type : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 limit1 : 4; + uint32 available : 1; + uint32 unused1 : 2; + uint32 granularity : 1; + uint32 base1 : 8; + uint32 base2 : 32; + uint32 unused2 : 32; +} _PACKED; + +// Structure of an interrupt descriptor. +struct interrupt_descriptor { + uint32 base0 : 16; + uint32 sel : 16; + uint32 ist : 3; + uint32 unused1 : 5; + uint32 type : 4; + uint32 unused2 : 1; + uint32 dpl : 2; + uint32 present : 1; + uint32 base1 : 16; + uint32 base2 : 32; + uint32 reserved : 32; +} _PACKED; + +struct gdt_idt_descr { + uint16 limit; + addr_t base; +} _PACKED; + +struct tss { + uint32 _reserved1; + uint64 rsp0; + uint64 rsp1; + uint64 rsp2; + uint64 _reserved2; + uint64 ist1; + uint64 ist2; + uint64 ist3; + uint64 ist4; + uint64 ist5; + uint64 ist6; + uint64 ist7; + uint64 _reserved3; + uint16 _reserved4; + uint16 io_bitmap; +} _PACKED; + + +static inline void +clear_segment_descriptor(segment_descriptor* desc) +{ + *(uint64*)desc = 0; +} + + +static inline void +set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) +{ + clear_segment_descriptor(desc); + + // In 64-bit mode the CPU ignores the base/limit of code/data segments, + // it always treats base as 0 and does no limit checks. + desc->base0 = 0; + desc->base1 = 0; + desc->limit0 = 0xffff; + desc->limit1 = 0xf; + desc->granularity = 1; + + desc->type = type; + desc->desc_type = DT_CODE_DATA_SEGMENT; + desc->dpl = dpl; + desc->present = 1; + + desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0; + // Must be set to 1 for code segments only. +} + + +static inline void +set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) +{ + clear_segment_descriptor(_desc); + clear_segment_descriptor(&_desc[1]); + + // The TSS descriptor is a special format in 64-bit mode, it is 16 bytes + // instead of 8. + tss_descriptor* desc = (tss_descriptor*)_desc; + + desc->base0 = base & 0xffffff; + desc->base1 = (base >> 24) & 0xff; + desc->base2 = (base >> 32); + desc->limit0 = limit & 0xffff; + desc->limit1 = (limit >> 16) & 0xf; + + desc->present = 1; + desc->type = DT_TSS; + desc->desc_type = DT_SYSTEM_SEGMENT; + desc->dpl = DPL_KERNEL; +} + + +static inline void +set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type, + uint16 seg, uint32 dpl, uint32 ist) +{ + desc->base0 = addr & 0xffff; + desc->base1 = (addr >> 16) & 0xffff; + desc->base2 = (addr >> 32) & 0xffffffff; + desc->sel = seg; + desc->ist = ist; + desc->type = type; + desc->dpl = dpl; + desc->present = 1; + desc->unused1 = 0; + desc->unused2 = 0; + desc->reserved = 0; +} + + +#endif /* _ASSEMBLER */ + +#endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ diff --git a/headers/private/kernel/arch/x86/64/iframe.h b/headers/private/kernel/arch/x86/64/iframe.h new file mode 100644 index 0000000000..a0ca48f2c4 --- /dev/null +++ b/headers/private/kernel/arch/x86/64/iframe.h @@ -0,0 +1,40 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_ARCH_X86_64_IFRAME_H +#define _KERNEL_ARCH_X86_64_IFRAME_H + + +struct iframe { + uint64 type; + uint64 r15; + uint64 r14; + uint64 r13; + uint64 r12; + uint64 r11; + uint64 r10; + uint64 r9; + uint64 r8; + uint64 rbp; + uint64 rsi; + uint64 rdi; + uint64 rdx; + uint64 rcx; + uint64 rbx; + uint64 rax; + uint64 vector; + uint64 error_code; + uint64 rip; + uint64 cs; + uint64 flags; + + // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). + uint64 user_rsp; + uint64 user_ss; +} _PACKED; + +#define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) + + +#endif /* _KERNEL_ARCH_X86_64_IFRAME_H */ diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index cfe380c820..d5e284e006 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -1,5 +1,6 @@ /* * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -9,14 +10,170 @@ #define _KERNEL_ARCH_x86_CPU_H -#include "../common_x86/cpu.h" - #ifndef _ASSEMBLER -# ifndef _BOOT_MODE -# include -# endif + +#include +#include + +#ifdef __x86_64__ +# include +#else +# include #endif +#endif // !_ASSEMBLER + + +#undef PAUSE +#define PAUSE() asm volatile ("pause;") + + +// MSR registers (possibly Intel specific) +#define IA32_MSR_TSC 0x10 +#define IA32_MSR_APIC_BASE 0x1b + +#define IA32_MSR_MTRR_CAPABILITIES 0xfe +#define IA32_MSR_SYSENTER_CS 0x174 +#define IA32_MSR_SYSENTER_ESP 0x175 +#define IA32_MSR_SYSENTER_EIP 0x176 +#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff +#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 +#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 + +// K8 MSR registers +#define K8_MSR_IPM 0xc0010055 + +// x86 features from cpuid eax 1, edx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) +#define IA32_FEATURE_FPU (1 << 0) // x87 fpu +#define IA32_FEATURE_VME (1 << 1) // virtual 8086 +#define IA32_FEATURE_DE (1 << 2) // debugging extensions +#define IA32_FEATURE_PSE (1 << 3) // page size extensions +#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction +#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction +#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing +#define IA32_FEATURE_MCE (1 << 7) // machine check exception +#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction +#define IA32_FEATURE_APIC (1 << 9) // local apic on chip +// (1 << 10) // Reserved +#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT +#define IA32_FEATURE_MTRR (1 << 12) // MTRR +#define IA32_FEATURE_PGE (1 << 13) // paging global bit +#define IA32_FEATURE_MCA (1 << 14) // machine check architecture +#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction +#define IA32_FEATURE_PAT (1 << 16) // page attribute table +#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages +#define IA32_FEATURE_PSN (1 << 18) // processor serial number +#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction +// (1 << 20) // Reserved +#define IA32_FEATURE_DS (1 << 21) // debug store +#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl +#define IA32_FEATURE_MMX (1 << 23) // mmx instructions +#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction +#define IA32_FEATURE_SSE (1 << 25) // SSE +#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 +#define IA32_FEATURE_SS (1 << 27) // self snoop +#define IA32_FEATURE_HTT (1 << 28) // hyperthreading +#define IA32_FEATURE_TM (1 << 29) // thermal monitor +#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 +#define IA32_FEATURE_PBE (1 << 31) // pending break enable + +// x86 features from cpuid eax 1, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) +#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 +#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction +#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store +#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT +#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store +#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions +#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions +#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep +#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 +#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 +#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID +// (1 << 11) // Reserved +#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add +#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B +#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control +#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability +// (1 << 16) // Reserved +#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers +#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access +#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 +#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 +#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support +#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction +#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction +#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline +#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions +#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States +#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE +#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions +#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion +#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction +#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor + +// x86 features from cpuid eax 0x80000001, edx register (AMD) +// only care about the ones that are unique to this register +#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET +#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit +#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions +#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR +#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction +#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode +#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions +#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! + +// x86 defined features from cpuid eax 6, eax register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor +#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology +#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer +#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification +#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty +#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management + +// x86 defined features from cpuid eax 6, ecx register +// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) +#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF +#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS + +// cr4 flags +#define IA32_CR4_PAE (1UL << 5) +#define IA32_CR4_GLOBAL_PAGES (1UL << 7) + +// Memory type ranges +#define IA32_MTR_UNCACHED 0 +#define IA32_MTR_WRITE_COMBINING 1 +#define IA32_MTR_WRITE_THROUGH 4 +#define IA32_MTR_WRITE_PROTECTED 5 +#define IA32_MTR_WRITE_BACK 6 + +// EFLAGS register +#define X86_EFLAGS_CARRY 0x00000001 +#define X86_EFLAGS_RESERVED1 0x00000002 +#define X86_EFLAGS_PARITY 0x00000004 +#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 +#define X86_EFLAGS_ZERO 0x00000040 +#define X86_EFLAGS_SIGN 0x00000080 +#define X86_EFLAGS_TRAP 0x00000100 +#define X86_EFLAGS_INTERRUPT 0x00000200 +#define X86_EFLAGS_DIRECTION 0x00000400 +#define X86_EFLAGS_OVERFLOW 0x00000800 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 +#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 +#define X86_EFLAGS_NESTED_TASK 0x00004000 +#define X86_EFLAGS_RESUME 0x00010000 +#define X86_EFLAGS_V86_MODE 0x00020000 +#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 +#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 +#define X86_EFLAGS_ID 0x00200000 + +#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ + | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ + | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) + // iframe types #define IFRAME_TYPE_SYSCALL 0x1 @@ -26,87 +183,64 @@ #ifndef _ASSEMBLER + struct X86PagingStructures; -struct tss { - uint16 prev_task; - uint16 unused0; - uint32 sp0; - uint32 ss0; - uint32 sp1; - uint32 ss1; - uint32 sp2; - uint32 ss2; - uint32 cr3; - uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; - uint32 es, cs, ss, ds, fs, gs; - uint32 ldt_seg_selector; - uint16 unused1; - uint16 io_map_base; + +typedef struct x86_mtrr_info { + uint64 base; + uint64 size; + uint8 type; +} x86_mtrr_info; + +typedef struct x86_optimized_functions { + void (*memcpy)(void* dest, const void* source, size_t count); + void* memcpy_end; + void (*memset)(void* dest, int value, size_t count); + void* memset_end; +} x86_optimized_functions; + +typedef struct x86_cpu_module_info { + module_info info; + uint32 (*count_mtrrs)(void); + void (*init_mtrrs)(void); + + void (*set_mtrr)(uint32 index, uint64 base, uint64 length, + uint8 type); + status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, + uint8* _type); + void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, + uint32 count); + + void (*get_optimized_functions)(x86_optimized_functions* functions); +} x86_cpu_module_info; + +// features +enum x86_feature_type { + FEATURE_COMMON = 0, // cpuid eax=1, ecx register + FEATURE_EXT, // cpuid eax=1, edx register + FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) + FEATURE_6_EAX, // cpuid eax=6, eax registers + FEATURE_6_ECX, // cpuid eax=6, ecx registers + + FEATURE_NUM }; -struct iframe { - uint32 type; // iframe type - uint32 gs; - uint32 fs; - uint32 es; - uint32 ds; - uint32 edi; - uint32 esi; - uint32 ebp; - uint32 esp; - uint32 ebx; - uint32 edx; - uint32 ecx; - uint32 eax; - uint32 orig_eax; - uint32 orig_edx; - uint32 vector; - uint32 error_code; - uint32 eip; - uint32 cs; - uint32 flags; +enum x86_vendors { + VENDOR_INTEL = 0, + VENDOR_AMD, + VENDOR_CYRIX, + VENDOR_UMC, + VENDOR_NEXGEN, + VENDOR_CENTAUR, + VENDOR_RISE, + VENDOR_TRANSMETA, + VENDOR_NSC, - // user_esp and user_ss are only present when the iframe is a userland - // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. - uint32 user_esp; - uint32 user_ss; + VENDOR_NUM, + VENDOR_UNKNOWN, }; -struct vm86_iframe { - uint32 type; // iframe type - uint32 __null_gs; - uint32 __null_fs; - uint32 __null_es; - uint32 __null_ds; - uint32 edi; - uint32 esi; - uint32 ebp; - uint32 __kern_esp; - uint32 ebx; - uint32 edx; - uint32 ecx; - uint32 eax; - uint32 orig_eax; - uint32 orig_edx; - uint32 vector; - uint32 error_code; - uint32 eip; - uint16 cs, __csh; - uint32 flags; - uint32 esp; - uint16 ss, __ssh; - - /* vm86 mode specific part */ - uint16 es, __esh; - uint16 ds, __dsh; - uint16 fs, __fsh; - uint16 gs, __gsh; -}; - -#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ - || ((f)->flags & 0x20000) != 0) -#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) typedef struct arch_cpu_info { // saved cpu info @@ -128,15 +262,86 @@ typedef struct arch_cpu_info { // local TSS for this cpu struct tss tss; +#ifndef __x86_64__ struct tss double_fault_tss; +#endif } arch_cpu_info; +#define nop() __asm__ ("nop"::) + +#define read_cr2(value) \ + __asm__("mov %%cr2,%0" : "=r" (value)) + +#define read_cr3(value) \ + __asm__("mov %%cr3,%0" : "=r" (value)) + +#define write_cr3(value) \ + __asm__("mov %0,%%cr3" : : "r" (value)) + +#define read_dr3(value) \ + __asm__("mov %%dr3,%0" : "=r" (value)) + +#define write_dr3(value) \ + __asm__("mov %0,%%dr3" : : "r" (value)) + +#define invalidate_TLB(va) \ + __asm__("invlpg (%0)" : : "r" (va)) + +#define wbinvd() \ + __asm__("wbinvd") + +#define out8(value,port) \ + __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) + +#define out16(value,port) \ + __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) + +#define out32(value,port) \ + __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) + +#define in8(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in16(port) ({ \ + uint16 _v; \ + __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define in32(port) ({ \ + uint32 _v; \ + __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ + _v; \ +}) + +#define out8_p(value,port) \ + __asm__ ("outb %%al,%%dx\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : : "a" (value), "d" (port)) + +#define in8_p(port) ({ \ + uint8 _v; \ + __asm__ volatile ("inb %%dx,%%al\n" \ + "\tjmp 1f\n" \ + "1:\tjmp 1f\n" \ + "1:" : "=a" (_v) : "d" (port)); \ + _v; \ +}) + + #ifdef __cplusplus extern "C" { #endif +// temporary +#ifndef __x86_64__ + struct arch_thread; void __x86_setup_system_time(uint32 conversionFactor, @@ -176,12 +381,12 @@ int32 x86_double_fault_get_cpu(void); void x86_double_fault_exception(struct iframe* frame); void x86_page_fault_exception_double_fault(struct iframe* frame); - -#ifndef _BOOT_MODE -extern segment_descriptor* gGDT; #endif +extern segment_descriptor* gGDT; + + #ifdef __cplusplus } // extern "C" { #endif diff --git a/headers/private/kernel/arch/x86/arch_int.h b/headers/private/kernel/arch/x86/arch_int.h index b8a5828d23..f00b56e91e 100644 --- a/headers/private/kernel/arch/x86/arch_int.h +++ b/headers/private/kernel/arch/x86/arch_int.h @@ -1,5 +1,6 @@ /* * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. */ #ifndef _KERNEL_ARCH_x86_INT_H @@ -20,30 +21,30 @@ arch_int_enable_interrupts_inline(void) static inline int arch_int_disable_interrupts_inline(void) { - int flags; + unsigned long flags; - asm volatile("pushfl;\n" - "popl %0;\n" + asm volatile("pushf;\n" + "pop %0;\n" "cli" : "=g" (flags)); - return flags ; + return (flags & 0x200) != 0; } static inline void arch_int_restore_interrupts_inline(int oldState) { - if (oldState & 0x200) - asm("sti"); + if (oldState) + asm("sti"); } static inline bool arch_int_are_interrupts_enabled_inline(void) { - int flags; + unsigned long flags; - asm volatile("pushfl;\n" - "popl %0;\n" : "=g" (flags)); + asm volatile("pushf;\n" + "pop %0;\n" : "=g" (flags)); return (flags & 0x200) != 0; } diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 00e2ea868d..a30eb94656 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -1,6 +1,6 @@ /* * Copyright 2004-2008, Haiku Inc. All rights reserved. - * Distributes under the terms of the MIT license. + * Distributed under the terms of the MIT license. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. @@ -8,19 +8,53 @@ #ifndef _KERNEL_ARCH_x86_KERNEL_H #define _KERNEL_ARCH_x86_KERNEL_H + #ifndef _ASSEMBLER # include #endif + +#ifdef _BOOT_MODE + + +// 32-bit and 64-bit kernel load addresses. +#define KERNEL_BASE 0x80000000 +#define KERNEL_BASE_64BIT 0xffffffff80000000ll + + +#elif defined(__x86_64__) + + +// Base of the kernel address space. +// When compiling the bootloader, KERNEL_BASE is set to the x86 base address, +// KERNEL_BASE_64BIT is set to where the kernel loaded to. +// For the kernel, KERNEL_BASE is the base of the kernel address space. This is +// NOT the address where the kernel is loaded to: the kernel is loaded in the +// top 2GB of the virtual address space as required by GCC's kernel code model. +// The whole kernel address space is the top 512GB of the address space. +#define KERNEL_BASE 0xffffff8000000000 +#define KERNEL_SIZE 0x8000000000 +#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) + +// Userspace address space layout. +#define USER_BASE 0x0 +#define USER_BASE_ANY 0x100000 +#define USER_SIZE 0x800000000000 +#define USER_TOP (USER_BASE + USER_SIZE) + +#define KERNEL_USER_DATA_BASE 0x7fffefff0000 +#define USER_STACK_REGION 0x7ffff0000000 +#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) + + +#else // __x86_64__ + + // memory layout #define KERNEL_BASE 0x80000000 #define KERNEL_SIZE 0x80000000 #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) -#ifdef _BOOT_MODE -# define KERNEL_BASE_64BIT 0xffffffff80000000ll -#endif - /* User space layout is a little special: * The user space does not completely cover the space not covered by the * kernel. There is a gap of 64kb between the user and kernel space. The 64kb @@ -40,4 +74,7 @@ #define USER_STACK_REGION 0x70000000 #define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) -#endif /* _KERNEL_ARCH_x86_KERNEL_H */ + +#endif // __x86_64__ + +#endif // _KERNEL_ARCH_x86_KERNEL_H diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index f0513717c9..567d4caff0 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -16,39 +16,65 @@ extern "C" { #endif -struct iframe *i386_get_user_iframe(void); -struct iframe *i386_get_current_iframe(void); -struct iframe *i386_get_thread_user_iframe(Thread *thread); -uint32 x86_next_page_directory(Thread *from, Thread *to); +struct iframe* i386_get_user_iframe(void); +struct iframe* i386_get_current_iframe(void); +struct iframe* i386_get_thread_user_iframe(Thread* thread); -void x86_restart_syscall(struct iframe *frame); +uint32 x86_next_page_directory(Thread* from, Thread* to); + +void x86_restart_syscall(struct iframe* frame); + +void x86_set_tls_context(Thread* thread); + + +#ifdef __x86_64__ + + +// TODO +static inline Thread* +arch_thread_get_current_thread(void) +{ + return NULL; +} + + +static inline void +arch_thread_set_current_thread(Thread* t) +{ + +} + + +#else // __x86_64__ -void x86_set_tls_context(Thread *thread); // override empty macro #undef arch_syscall_64_bit_return_value void arch_syscall_64_bit_return_value(void); -static -inline Thread * +static inline Thread* arch_thread_get_current_thread(void) { - Thread *t; + Thread* t; read_dr3(t); return t; } + static inline void -arch_thread_set_current_thread(Thread *t) +arch_thread_set_current_thread(Thread* t) { write_dr3(t); } + +#endif // __x86_64__ + + #ifdef __cplusplus } #endif #endif /* _KERNEL_ARCH_x86_THREAD_H */ - diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 0df49071c0..900046fd0b 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -11,23 +11,31 @@ #include + #define _ALIGNED(bytes) __attribute__((aligned(bytes))) // move this to somewhere else, maybe BeBuild.h? + struct farcall { - uint32 *esp; - uint32 *ss; + uint32* esp; + uint32* ss; }; + // architecture specific thread info struct arch_thread { +#ifdef __x86_64__ + uint64* rsp; +#else struct farcall current_stack; struct farcall interrupt_stack; +#endif // 512 byte floating point save point - this must be 16 byte aligned - uint8 fpu_state[512]; + uint8 fpu_state[512] _ALIGNED(16); } _ALIGNED(16); + struct arch_team { // gcc treats empty structures as zero-length in C, but as if they contain // a char in C++. So we have to put a dummy in to be able to use the struct @@ -35,8 +43,10 @@ struct arch_team { char dummy; }; + struct arch_fork_arg { struct iframe iframe; }; + #endif /* _KERNEL_ARCH_x86_THREAD_TYPES_H */ diff --git a/headers/private/kernel/arch/x86/descriptors.h b/headers/private/kernel/arch/x86/descriptors.h index 19d7e93a71..69699c8745 100644 --- a/headers/private/kernel/arch/x86/descriptors.h +++ b/headers/private/kernel/arch/x86/descriptors.h @@ -9,45 +9,8 @@ #define _KERNEL_ARCH_x86_DESCRIPTORS_H -#define KERNEL_CODE_SEG 0x8 -#define KERNEL_DATA_SEG 0x10 - -#define USER_CODE_SEG 0x1b -#define USER_DATA_SEG 0x23 - -#define APM_CODE32_SEGMENT 0x28 -#define APM_CODE16_SEGMENT 0x30 -#define APM_DATA_SEGMENT 0x38 - -#define BIOS_DATA_SEGMENT 0x40 - #ifndef _ASSEMBLER - // this file can also be included from assembler as well - // (and is in arch_interrupts.S) -#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 -#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) - - -// defines entries in the GDT/LDT - -typedef struct segment_descriptor { - uint16 limit_00_15; // bit 0 - 15 - uint16 base_00_15; // 16 - 31 - uint32 base_23_16 : 8; // 0 - 7 - uint32 type : 4; // 8 - 11 - uint32 desc_type : 1; // 12 (0 = system, 1 = code/data) - uint32 privilege_level : 2; // 13 - 14 - uint32 present : 1; // 15 - uint32 limit_19_16 : 4; // 16 - 19 - uint32 available : 1; // 20 - uint32 zero : 1; // 21 - uint32 d_b : 1; // 22 - uint32 granularity : 1; // 23 - uint32 base_31_24 : 8; // 24 - 31 -} segment_descriptor; enum descriptor_privilege_levels { DPL_KERNEL = 0, @@ -73,74 +36,20 @@ enum descriptor_types { DT_CODE_DATA_SEGMENT = 1, }; -static inline void -clear_segment_descriptor(struct segment_descriptor *desc) -{ - *(long long *)desc = 0; -} +enum gate_types { + GATE_INTERRUPT = 14, + GATE_TRAP = 15, +}; -static inline void -set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) -{ - desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long - desc->base_23_16 = ((addr_t)base >> 16) & 0xff; - desc->base_31_24 = ((addr_t)base >> 24) & 0xff; -} +#endif // !_ASSEMBLER -static inline void -set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, - uint8 type, uint8 privilegeLevel) -{ - set_segment_descriptor_base(desc, base); +#ifdef __x86_64__ +# include +#else +# include +#endif - // limit is 20 bits long - if (limit & 0xfff00000) { - desc->limit_00_15 = ((addr_t)limit >> 12) & 0x0ffff; - desc->limit_19_16 = ((addr_t)limit >> 28) & 0xf; - desc->granularity = 1; // 4 KB granularity - } else { - desc->limit_00_15 = (addr_t)limit & 0x0ffff; - desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; - desc->granularity = 0; // 1 byte granularity - } - limit >>= 12; - - - desc->type = type; - desc->desc_type = DT_CODE_DATA_SEGMENT; - desc->privilege_level = privilegeLevel; - - desc->present = 1; - desc->available = 0; // system available bit is currently not used - desc->d_b = 1; // 32-bit code - - desc->zero = 0; -} - - -static inline void -set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) -{ - // the TSS descriptor has a special layout different from the standard descriptor - set_segment_descriptor_base(desc, base); - - desc->limit_00_15 = (addr_t)limit & 0x0ffff; - desc->limit_19_16 = 0; - - desc->type = DT_TSS; - desc->desc_type = DT_SYSTEM_SEGMENT; - desc->privilege_level = DPL_KERNEL; - - desc->present = 1; - desc->granularity = 0; // 1 Byte granularity - desc->available = 0; // system available bit is currently not used - desc->d_b = 0; - - desc->zero = 0; -} - -#endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_x86_DESCRIPTORS_H */ diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index cafc2ed3a2..567c5f34fc 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -8,7 +8,11 @@ #include -#include +// Include the x86_64 version of descriptors.h +#define __x86_64__ +#include +#undef __x86_64__ + #include #include #include From 020a25ce46175de76c694ef395fa364b2b7df6c9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 2 Jul 2012 20:56:27 +0100 Subject: [PATCH 055/273] Fixed x86_64 kernel compilation. For now I've just put all the stub functions that are needed to link the kernel into a file called stubs.cpp. I've not yet moved across the interrupt handling code or the ELF64 relocation code to the x86 directory. Once those have been moved I can get rid of the x86_64 headers/source directories. --- .../kernel/arch/x86/arch_system_info.h | 2 + src/system/kernel/arch/x86/64/stubs.cpp | 801 ++++++++++++++++++ src/system/kernel/arch/x86/Jamfile | 124 +-- 3 files changed, 874 insertions(+), 53 deletions(-) create mode 100644 src/system/kernel/arch/x86/64/stubs.cpp diff --git a/headers/private/kernel/arch/x86/arch_system_info.h b/headers/private/kernel/arch/x86/arch_system_info.h index e243607364..88b018d370 100644 --- a/headers/private/kernel/arch/x86/arch_system_info.h +++ b/headers/private/kernel/arch/x86/arch_system_info.h @@ -12,11 +12,13 @@ extern "C" { #endif +#ifndef __x86_64__ status_t get_current_cpuid(cpuid_info *info, uint32 eax); uint32 get_eflags(void); void set_eflags(uint32 value); status_t _user_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); +#endif #ifdef __cplusplus } diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp new file mode 100644 index 0000000000..d0cde670e7 --- /dev/null +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -0,0 +1,801 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +// This file contains stubs for everything that's not been implemented yet on +// x86_64. + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +status_t +arch_commpage_init(void) +{ + return B_OK; +} + + +status_t +arch_commpage_init_post_cpus(void) +{ + return B_OK; +} + + +status_t +arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) +{ + return B_OK; +} + + +status_t +arch_cpu_init_percpu(kernel_args* args, int cpu) +{ + return B_OK; +} + + +status_t +arch_cpu_init(kernel_args* args) +{ + return B_OK; +} + + +status_t +arch_cpu_init_post_vm(kernel_args* args) +{ + return B_OK; +} + + +status_t +arch_cpu_init_post_modules(kernel_args* args) +{ + return B_OK; +} + + +void +arch_cpu_user_TLB_invalidate(void) +{ + +} + + +void +arch_cpu_global_TLB_invalidate(void) +{ + +} + + +void +arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) +{ + +} + + +void +arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) +{ + +} + + +ssize_t +arch_cpu_user_strlcpy(char* to, const char* from, size_t size, + addr_t* faultHandler) +{ + return B_BAD_ADDRESS; +} + + +status_t +arch_cpu_user_memcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) +{ + return B_BAD_ADDRESS; +} + + +status_t +arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) +{ + return B_BAD_ADDRESS; +} + + +status_t +arch_cpu_shutdown(bool rebootSystem) +{ + return B_ERROR; +} + + +void +arch_cpu_idle(void) +{ + asm("hlt"); +} + + +void +arch_cpu_sync_icache(void* address, size_t length) +{ + // Instruction cache is always consistent on x86. +} + + +void +arch_cpu_memory_read_barrier(void) +{ + asm volatile("lfence" : : : "memory"); +} + + +void +arch_cpu_memory_write_barrier(void) +{ + asm volatile("sfence" : : : "memory"); +} + + +void +arch_debug_save_registers(struct arch_debug_registers* registers) +{ + +} + + +void +arch_debug_stack_trace(void) +{ + +} + + +bool +arch_debug_contains_call(Thread *thread, const char *symbol, + addr_t start, addr_t end) +{ + return false; +} + + +void * +arch_debug_get_caller(void) +{ + return NULL; +} + + +int32 +arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, + int32 skipIframes, int32 skipFrames, uint32 flags) +{ + return 0; +} + + +void* +arch_debug_get_interrupt_pc(bool* _isSyscall) +{ + return NULL; +} + + +void +arch_debug_unset_current_thread(void) +{ + +} + + +bool +arch_is_debug_variable_defined(const char* variableName) +{ + return false; +} + + +status_t +arch_set_debug_variable(const char* variableName, uint64 value) +{ + return B_OK; +} + + +status_t +arch_get_debug_variable(const char* variableName, uint64* value) +{ + return B_OK; +} + + +ssize_t +arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) +{ + return B_ERROR; +} + + +status_t +arch_debug_init(kernel_args *args) +{ + return B_OK; +} + +void +arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, + void (*function)(void*), void* parameter) +{ + // To be implemented in asm, not here. +} + + +status_t +arch_platform_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_platform_init_post_vm(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_platform_init_post_thread(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_rtc_init(struct kernel_args *args, struct real_time_data *data) +{ + return B_OK; +} + + +uint32 +arch_rtc_get_hw_time(void) +{ + return 0; +} + + +void +arch_rtc_set_hw_time(uint32 seconds) +{ + +} + + +void +arch_rtc_set_system_time_offset(struct real_time_data *data, bigtime_t offset) +{ + +} + + +bigtime_t +arch_rtc_get_system_time_offset(struct real_time_data *data) +{ + return 0; +} + + +status_t +arch_smp_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_smp_per_cpu_init(kernel_args *args, int32 cpu) +{ + return B_OK; +} + + +void +arch_smp_send_broadcast_ici(void) +{ + +} + + +void +arch_smp_send_ici(int32 target_cpu) +{ + +} + + +status_t +arch_get_system_info(system_info *info, size_t size) +{ + return B_OK; +} + + +status_t +arch_system_info_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_thread_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_team_init_team_struct(Team *p, bool kernel) +{ + return B_ERROR; +} + + +status_t +arch_thread_init_thread_struct(Thread *thread) +{ + return B_ERROR; +} + + +void +arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, + void (*function)(void*), const void* data) +{ + +} + + +status_t +arch_thread_init_tls(Thread *thread) +{ + return B_ERROR; +} + + +void +arch_thread_context_switch(Thread *from, Thread *to) +{ + +} + + +void +arch_thread_dump_info(void *info) +{ + +} + + +status_t +arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, + void* args2) +{ + return B_ERROR; +} + + +bool +arch_on_signal_stack(Thread *thread) +{ + return false; +} + + +status_t +arch_setup_signal_frame(Thread* thread, struct sigaction* action, + struct signal_frame_data* signalFrameData) +{ + return B_ERROR; +} + + +int64 +arch_restore_signal_frame(struct signal_frame_data* signalFrameData) +{ + return 0; +} + + +void +arch_store_fork_frame(struct arch_fork_arg *arg) +{ + +} + + +void +arch_restore_fork_frame(struct arch_fork_arg* arg) +{ + +} + + +void +arch_timer_set_hardware_timer(bigtime_t timeout) +{ + +} + + +void +arch_timer_clear_hardware_timer(void) +{ + +} + + +int +arch_init_timer(kernel_args *args) +{ + return 0; +} + + +// The software breakpoint instruction (int3). +const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; + + +void +arch_clear_team_debug_info(struct arch_team_debug_info *info) +{ + +} + + +void +arch_destroy_team_debug_info(struct arch_team_debug_info *info) +{ + +} + + +void +arch_clear_thread_debug_info(struct arch_thread_debug_info *info) +{ + +} + + +void +arch_destroy_thread_debug_info(struct arch_thread_debug_info *info) +{ + +} + + +void +arch_update_thread_single_step() +{ + +} + + +void +arch_set_debug_cpu_state(const debug_cpu_state *cpuState) +{ + +} + + +void +arch_get_debug_cpu_state(debug_cpu_state *cpuState) +{ + +} + + +status_t +arch_set_breakpoint(void *address) +{ + return B_OK; +} + + +status_t +arch_clear_breakpoint(void *address) +{ + return B_OK; +} + + +status_t +arch_set_watchpoint(void *address, uint32 type, int32 length) +{ + return B_OK; +} + + +status_t +arch_clear_watchpoint(void *address) +{ + return B_OK; +} + + +bool +arch_has_breakpoints(struct arch_team_debug_info *info) +{ + return false; +} + + +void +x86_init_user_debug() +{ + +} + + +status_t +arch_vm_init(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_post_area(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_end(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_init_post_modules(kernel_args *args) +{ + return B_OK; +} + + +void +arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to) +{ + +} + + +bool +arch_vm_supports_protection(uint32 protection) +{ + return true; +} + + +void +arch_vm_unset_memory_type(struct VMArea *area) +{ + +} + + +status_t +arch_vm_set_memory_type(struct VMArea *area, phys_addr_t physicalBase, + uint32 type) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map) +{ + return B_ERROR; +} + + +status_t +arch_vm_translation_map_init(kernel_args *args, + VMPhysicalPageMapper** _physicalPageMapper) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_init_post_sem(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_init_post_area(kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_vm_translation_map_early_map(kernel_args *args, addr_t va, phys_addr_t pa, + uint8 attributes, phys_addr_t (*get_free_page)(kernel_args *)) +{ + return B_ERROR; +} + + +bool +arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, + uint32 protection) +{ + return true; +} + + +void +arch_int_enable_io_interrupt(int irq) +{ + +} + + +void +arch_int_disable_io_interrupt(int irq) +{ + +} + + +void +arch_int_configure_io_interrupt(int irq, uint32 config) +{ + +} + + +status_t +arch_int_init(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_int_init_post_vm(struct kernel_args *args) +{ + return B_OK; +} + + +status_t +arch_int_init_io(kernel_args* args) +{ + return B_OK; +} + + +status_t +arch_int_init_post_device_manager(struct kernel_args *args) +{ + return B_OK; +} + + +// Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. + +status_t +elf_load_user_image(const char *path, Team *team, int flags, addr_t *_entry) +{ + return B_ERROR; +} + +image_id +load_kernel_add_on(const char *path) +{ + return 0; +} + +status_t +unload_kernel_add_on(image_id id) +{ + return B_ERROR; +} + +status_t +elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, + const char **_symbolName, const char **_imageName, bool *_exactMatch) +{ + return B_ERROR; +} + +addr_t +elf_debug_lookup_symbol(const char* searchName) +{ + return 0; +} + +struct elf_image_info * +elf_get_kernel_image() +{ + return NULL; +} + +image_id +elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, + addr_t data, size_t dataSize) +{ + return B_ERROR; +} + +status_t +elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, + size_t size, int32 type) +{ + return B_ERROR; +} + +status_t +elf_init(struct kernel_args *args) +{ + return B_OK; +} + +status_t +get_image_symbol(image_id image, const char *name, int32 symbolType, + void **_symbolLocation) +{ + return B_OK; +} + +status_t +_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, + int32* _symbolCount, char* stringTable, size_t* _stringTableSize, + addr_t* _imageDelta) +{ + return B_ERROR; +} diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index ecb9706398..60ec7ccd9a 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -15,61 +15,79 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) paging 32bit ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) paging pae ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ; +local archSpecificSources ; +if $(TARGET_ARCH) = x86_64 { + SEARCH_SOURCE += [ FDirName $(SUBDIR) 64 ] ; + + archSpecificSources = + stubs.cpp + ; +} else { + SEARCH_SOURCE += [ FDirName $(SUBDIR) 32 ] ; + + archSpecificSources = + arch_commpage.cpp + arch_cpu.cpp + arch_debug.cpp + arch_elf.cpp + arch_int.cpp + arch_platform.cpp +# arch_selector.cpp + arch_real_time_clock.cpp + arch_smp.cpp + arch_thread.cpp + arch_timer.cpp + arch_vm.cpp + arch_vm_translation_map.cpp + arch_x86.S + arch_interrupts.S + arch_system_info.cpp + arch_user_debugger.cpp + apic.cpp + apm.cpp + bios.cpp + cpuid.S + ioapic.cpp + irq_routing_table.cpp + msi.cpp + pic.cpp + syscall.S + vm86.cpp + x86_signals.cpp + x86_signals_asm.S + x86_syscalls.cpp + + # paging + x86_physical_page_mapper.cpp + x86_physical_page_mapper_large_memory.cpp + X86PagingMethod.cpp + X86PagingStructures.cpp + X86VMTranslationMap.cpp + + # paging/32bit + X86PagingMethod32Bit.cpp + X86PagingStructures32Bit.cpp + X86VMTranslationMap32Bit.cpp + + # paging/pae + X86PagingMethodPAE.cpp + X86PagingStructuresPAE.cpp + X86VMTranslationMapPAE.cpp + + # timers + x86_apic.cpp + x86_hpet.cpp + x86_pit.cpp + ; +} + +local archGenericSources = + arch_debug_console.cpp +; KernelMergeObject kernel_arch_x86.o : - arch_commpage.cpp - arch_cpu.cpp - arch_debug.cpp - arch_debug_console.cpp - arch_elf.cpp - arch_int.cpp - arch_platform.cpp -# arch_selector.cpp - arch_real_time_clock.cpp - arch_smp.cpp - arch_thread.cpp - arch_timer.cpp - arch_vm.cpp - arch_vm_translation_map.cpp - arch_x86.S - arch_interrupts.S - arch_system_info.cpp - arch_user_debugger.cpp - apic.cpp - apm.cpp - bios.cpp - cpuid.S - ioapic.cpp - irq_routing_table.cpp - msi.cpp - pic.cpp - syscall.S - vm86.cpp - x86_signals.cpp - x86_signals_asm.S - x86_syscalls.cpp - - # paging - x86_physical_page_mapper.cpp - x86_physical_page_mapper_large_memory.cpp - X86PagingMethod.cpp - X86PagingStructures.cpp - X86VMTranslationMap.cpp - - # paging/32bit - X86PagingMethod32Bit.cpp - X86PagingStructures32Bit.cpp - X86VMTranslationMap32Bit.cpp - - # paging/pae - X86PagingMethodPAE.cpp - X86PagingStructuresPAE.cpp - X86VMTranslationMapPAE.cpp - - # timers - x86_apic.cpp - x86_hpet.cpp - x86_pit.cpp + $(archSpecificSources) + $(archGenericSources) : $(TARGET_KERNEL_PIC_CCFLAGS) ; From 90907c35ac51e760221470563fdcd90a9232cc51 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 3 Jul 2012 08:45:35 +0100 Subject: [PATCH 056/273] Moved ELF64 relocation functions to x86 arch_elf.cpp. --- src/system/boot/arch/x86/Jamfile | 7 -- src/system/boot/arch/x86/arch_elf64.cpp | 1 - src/system/kernel/arch/x86/arch_elf.cpp | 95 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 8 deletions(-) delete mode 100644 src/system/boot/arch/x86/arch_elf64.cpp diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index 1ef6a979c5..f373212aa7 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -2,10 +2,6 @@ SubDir HAIKU_TOP src system boot arch x86 ; DEFINES += _BOOT_MODE ; -local bootArchSources = - arch_elf64.cpp -; - local kernelArchSources = arch_elf.cpp cpuid.S @@ -20,15 +16,12 @@ local librootOsArchSources = ; BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : - $(bootArchSources) $(kernelArchSources) $(kernelLibArchSources) $(librootOsArchSources) : # additional flags ; -SEARCH on [ FGristFiles $(bootArchSources) ] - = [ FDirName $(HAIKU_TOP) src system boot arch x86 ] ; SEARCH on [ FGristFiles $(kernelArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; SEARCH on [ FGristFiles $(kernelLibArchSources) ] diff --git a/src/system/boot/arch/x86/arch_elf64.cpp b/src/system/boot/arch/x86/arch_elf64.cpp deleted file mode 100644 index 41e0198ea1..0000000000 --- a/src/system/boot/arch/x86/arch_elf64.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "../../../kernel/arch/x86_64/arch_elf.cpp" diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index 20570527d0..951a33dde5 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -25,6 +25,9 @@ #endif +#if !defined(__x86_64__) || defined(_BOOT_MODE) + + #ifdef TRACE_ARCH_ELF static const char *kRelocations[] = { "R_386_NONE", @@ -178,3 +181,95 @@ arch_elf_relocate_rela(struct elf_image_info *image, dprintf("arch_elf_relocate_rela: not supported on x86\n"); return B_ERROR; } + + +#endif // !__x86_64__ || _BOOT_MODE + + +//#if defined(__x86_64__) || defined(_BOOT_MODE) +#ifdef _BOOT_MODE + + +#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rel(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) +//#endif +{ + dprintf("arch_elf_relocate_rel: not supported on x86_64\n"); + return B_ERROR; +} + + +//#ifdef _BOOT_MODE +status_t +boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, + int relLength) +//#else +//int +//arch_elf_relocate_rela(struct elf_image_info *image, +// struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) +//#endif +{ + for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { + int type = ELF64_R_TYPE(rel[i].r_info); + int symIndex = ELF64_R_SYM(rel[i].r_info); + Elf64_Addr symAddr = 0; + + // Resolve the symbol, if any. + if (symIndex != 0) { + Elf64_Sym* symbol = SYMBOL(image, symIndex); + + status_t status; +//#ifdef _BOOT_MODE + status = boot_elf_resolve_symbol(image, symbol, &symAddr); +//#else +// status = elf_resolve_symbol(image, symbol, resolveImage, &S); +//#endif + if (status < B_OK) + return status; + } + + // Address of the relocation. + Elf64_Addr relocAddr = image->text_region.delta + rel[i].r_offset; + + // Calculate the relocation value. + Elf64_Addr relocValue; + switch(type) { + case R_X86_64_NONE: + continue; + case R_X86_64_64: + relocValue = symAddr + rel[i].r_addend; + break; + case R_X86_64_PC32: + relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + relocValue = symAddr + rel[i].r_addend; + break; + case R_X86_64_RELATIVE: + relocValue = image->text_region.delta + rel[i].r_addend; + break; + default: + dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", + type); + return B_BAD_DATA; + } +#ifdef _BOOT_MODE + boot_elf64_set_relocation(relocAddr, relocValue); +#else + *(Elf64_Addr *)relocAddr = relocValue; +#endif + } + + return B_OK; +} +#endif + + +#endif // __x86_64__ || _BOOT_MODE From 4f419b518fca1017a0950eef8fb55cb07628f3d5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 3 Jul 2012 11:13:51 +0100 Subject: [PATCH 057/273] Merged in the x86_64 exception handling. I've split the 32-bit dependent IDT setup code and ASM interrupt handlers to the 32 subdirectory, arch_int.cpp now contains only the generic hardware interrupt handling code. --- src/system/kernel/arch/x86/32/int.cpp | 774 ++++++++++++++++ .../{arch_interrupts.S => 32/interrupts.S} | 0 .../kernel/arch/x86/{ => 32}/interrupts.h | 0 .../{x86_64/arch_int.cpp => x86/64/int.cpp} | 56 +- .../arch_interrupts.S => x86/64/interrupts.S} | 4 +- src/system/kernel/arch/x86/64/stubs.cpp | 51 -- src/system/kernel/arch/x86/Jamfile | 10 +- src/system/kernel/arch/x86/arch_int.cpp | 838 ++---------------- src/system/kernel/arch/x86/asm_offsets.cpp | 6 + 9 files changed, 858 insertions(+), 881 deletions(-) create mode 100644 src/system/kernel/arch/x86/32/int.cpp rename src/system/kernel/arch/x86/{arch_interrupts.S => 32/interrupts.S} (100%) rename src/system/kernel/arch/x86/{ => 32}/interrupts.h (100%) rename src/system/kernel/arch/{x86_64/arch_int.cpp => x86/64/int.cpp} (90%) rename src/system/kernel/arch/{x86_64/arch_interrupts.S => x86/64/interrupts.S} (97%) diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp new file mode 100644 index 0000000000..fe54d5800f --- /dev/null +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -0,0 +1,774 @@ +/* + * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch. + * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de. + * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "interrupts.h" + +#include + + +static const char *kInterruptNames[] = { + /* 0 */ "Divide Error Exception", + /* 1 */ "Debug Exception", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint Exception", + /* 4 */ "Overflow Exception", + /* 5 */ "BOUND Range Exceeded Exception", + /* 6 */ "Invalid Opcode Exception", + /* 7 */ "Device Not Available Exception", + /* 8 */ "Double Fault Exception", + /* 9 */ "Coprocessor Segment Overrun", + /* 10 */ "Invalid TSS Exception", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Fault Exception", + /* 13 */ "General Protection Exception", + /* 14 */ "Page-Fault Exception", + /* 15 */ "-", + /* 16 */ "x87 FPU Floating-Point Error", + /* 17 */ "Alignment Check Exception", + /* 18 */ "Machine-Check Exception", + /* 19 */ "SIMD Floating-Point Exception", +}; +static const int kInterruptNameCount = 20; + +#define MAX_ARGS 16 + +typedef struct { + uint32 a, b; +} desc_table; +static desc_table* sIDTs[B_MAX_CPU_COUNT]; + +// table with functions handling respective interrupts +typedef void interrupt_handler_function(struct iframe* frame); + +#define INTERRUPT_HANDLER_TABLE_SIZE 256 +interrupt_handler_function* gInterruptHandlerTable[ + INTERRUPT_HANDLER_TABLE_SIZE]; + +extern void hardware_interrupt(struct iframe* frame); + + +/*! Initializes a descriptor in an IDT. +*/ +static void +set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl) +{ + unsigned int gate1; // first byte of gate desc + unsigned int gate2; // second byte of gate desc + + gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); + gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); + + gate_addr->a = gate1; + gate_addr->b = gate2; +} + + +/*! Initializes the descriptor for interrupt vector \a n in the IDT of the + specified CPU to an interrupt-gate descriptor with the given procedure + address. + For CPUs other than the boot CPU it must not be called before + arch_int_init_post_vm(). +*/ +static void +set_interrupt_gate(int32 cpu, int n, void (*addr)()) +{ + set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL); +} + + +/*! Initializes the descriptor for interrupt vector \a n in the IDT of the + specified CPU to an trap-gate descriptor with the given procedure address. + For CPUs other than the boot CPU it must not be called before + arch_int_init_post_vm(). +*/ +static void +set_trap_gate(int32 cpu, int n, void (*addr)()) +{ + set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER); +} + + +/*! Initializes the descriptor for interrupt vector \a n in the IDT of CPU + \a cpu to a task-gate descripter referring to the TSS segment identified + by TSS segment selector \a segment. + For CPUs other than the boot CPU it must not be called before + arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine). +*/ +void +x86_set_task_gate(int32 cpu, int32 n, int32 segment) +{ + sIDTs[cpu][n].a = (segment << 16); + sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5 +} + + +/*! Returns the virtual IDT address for CPU \a cpu. */ +void* +x86_get_idt(int32 cpu) +{ + return sIDTs[cpu]; +} + + +// #pragma mark - + + +static const char * +exception_name(int number, char *buffer, int32 bufferSize) +{ + if (number >= 0 && number < kInterruptNameCount) + return kInterruptNames[number]; + + snprintf(buffer, bufferSize, "exception %d", number); + return buffer; +} + + +static void +invalid_exception(struct iframe* frame) +{ + Thread* thread = thread_get_current_thread(); + char name[32]; + panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->eip, thread ? thread->id : -1); +} + + +static void +fatal_exception(struct iframe *frame) +{ + char name[32]; + panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), frame->error_code); +} + + +static void +unexpected_exception(struct iframe* frame) +{ + debug_exception_type type; + uint32 signalNumber; + int32 signalCode; + addr_t signalAddress = 0; + int32 signalError = B_ERROR; + + if (IFRAME_IS_VM86(frame)) { + x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? + B_OK : B_ERROR); + // won't get here + } + + switch (frame->vector) { + case 0: // Divide Error Exception (#DE) + type = B_DIVIDE_ERROR; + signalNumber = SIGFPE; + signalCode = FPE_INTDIV; + signalAddress = frame->eip; + break; + + case 4: // Overflow Exception (#OF) + type = B_OVERFLOW_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_INTOVF; + signalAddress = frame->eip; + break; + + case 5: // BOUND Range Exceeded Exception (#BR) + type = B_BOUNDS_CHECK_EXCEPTION; + signalNumber = SIGTRAP; + signalCode = SI_USER; + break; + + case 6: // Invalid Opcode Exception (#UD) + type = B_INVALID_OPCODE_EXCEPTION; + signalNumber = SIGILL; + signalCode = ILL_ILLOPC; + signalAddress = frame->eip; + break; + + case 13: // General Protection Exception (#GP) + type = B_GENERAL_PROTECTION_FAULT; + signalNumber = SIGILL; + signalCode = ILL_PRVOPC; // or ILL_PRVREG + signalAddress = frame->eip; + break; + + case 16: // x87 FPU Floating-Point Error (#MF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the FPU status + // register! + signalAddress = frame->eip; + break; + + case 17: // Alignment Check Exception (#AC) + type = B_ALIGNMENT_EXCEPTION; + signalNumber = SIGBUS; + signalCode = BUS_ADRALN; + // TODO: Also get the address (from where?). Since we don't enable + // alignment checking this exception should never happen, though. + signalError = EFAULT; + break; + + case 19: // SIMD Floating-Point Exception (#XF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the MXCSR register! + signalAddress = frame->eip; + break; + + default: + invalid_exception(frame); + return; + } + + if (IFRAME_IS_USER(frame)) { + struct sigaction action; + Thread* thread = thread_get_current_thread(); + + enable_interrupts(); + + // If the thread has a signal handler for the signal, we simply send it + // the signal. Otherwise we notify the user debugger first. + if ((sigaction(signalNumber, NULL, &action) == 0 + && action.sa_handler != SIG_DFL + && action.sa_handler != SIG_IGN) + || user_debug_exception_occurred(type, signalNumber)) { + Signal signal(signalNumber, signalCode, signalError, + thread->team->id); + signal.SetAddress((void*)signalAddress); + send_signal_to_thread(thread, signal, 0); + } + } else { + char name[32]; + panic("Unexpected exception \"%s\" occurred in kernel mode! " + "Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), + frame->error_code); + } +} + + +void +x86_double_fault_exception(struct iframe* frame) +{ + int cpu = x86_double_fault_get_cpu(); + + // The double fault iframe contains no useful information (as + // per Intel's architecture spec). Thus we simply save the + // information from the (unhandlable) exception which caused the + // double in our iframe. This will result even in useful stack + // traces. Only problem is that we trust that at least the + // TSS is still accessible. + struct tss *tss = &gCPU[cpu].arch.tss; + + frame->cs = tss->cs; + frame->es = tss->es; + frame->ds = tss->ds; + frame->fs = tss->fs; + frame->gs = tss->gs; + frame->eip = tss->eip; + frame->ebp = tss->ebp; + frame->esp = tss->esp; + frame->eax = tss->eax; + frame->ebx = tss->ebx; + frame->ecx = tss->ecx; + frame->edx = tss->edx; + frame->esi = tss->esi; + frame->edi = tss->edi; + frame->flags = tss->eflags; + + // Use a special handler for page faults which avoids the triple fault + // pitfalls. + set_interrupt_gate(cpu, 14, &trap14_double_fault); + + debug_double_fault(cpu); +} + + +void +x86_page_fault_exception_double_fault(struct iframe* frame) +{ + uint32 cr2; + asm("movl %%cr2, %0" : "=r" (cr2)); + + // Only if this CPU has a fault handler, we're allowed to be here. + cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; + addr_t faultHandler = cpu.fault_handler; + if (faultHandler != 0) { + debug_set_page_fault_info(cr2, frame->eip, + (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->eip = faultHandler; + frame->ebp = cpu.fault_handler_stack_pointer; + return; + } + + // No fault handler. This is bad. Since we originally came from a double + // fault, we don't try to reenter the kernel debugger. Instead we just + // print the info we've got and enter an infinite loop. + kprintf("Page fault in double fault debugger without fault handler! " + "Touching address %p from eip %p. Entering infinite loop...\n", + (void*)cr2, (void*)frame->eip); + + while (true); +} + + +static void +page_fault_exception(struct iframe* frame) +{ + Thread *thread = thread_get_current_thread(); + uint32 cr2; + addr_t newip; + + asm("movl %%cr2, %0" : "=r" (cr2)); + + if (debug_debugger_running()) { + // If this CPU or this thread has a fault handler, we're allowed to be + // here. + if (thread != NULL) { + cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; + if (cpu->fault_handler != 0) { + debug_set_page_fault_info(cr2, frame->eip, + (frame->error_code & 0x2) != 0 + ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->eip = cpu->fault_handler; + frame->ebp = cpu->fault_handler_stack_pointer; + return; + } + + if (thread->fault_handler != 0) { + kprintf("ERROR: thread::fault_handler used in kernel " + "debugger!\n"); + debug_set_page_fault_info(cr2, frame->eip, + (frame->error_code & 0x2) != 0 + ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->eip = thread->fault_handler; + return; + } + } + + // otherwise, not really + panic("page fault in debugger without fault handler! Touching " + "address %p from eip %p\n", (void *)cr2, (void *)frame->eip); + return; + } else if ((frame->flags & 0x200) == 0) { + // interrupts disabled + + // If a page fault handler is installed, we're allowed to be here. + // TODO: Now we are generally allowing user_memcpy() with interrupts + // disabled, which in most cases is a bug. We should add some thread + // flag allowing to explicitly indicate that this handling is desired. + if (thread && thread->fault_handler != 0) { + if (frame->eip != thread->fault_handler) { + frame->eip = thread->fault_handler; + return; + } + + // The fault happened at the fault handler address. This is a + // certain infinite loop. + panic("page fault, interrupts disabled, fault handler loop. " + "Touching address %p from eip %p\n", (void*)cr2, + (void*)frame->eip); + } + + // If we are not running the kernel startup the page fault was not + // allowed to happen and we must panic. + panic("page fault, but interrupts were disabled. Touching address " + "%p from eip %p\n", (void *)cr2, (void *)frame->eip); + return; + } else if (thread != NULL && thread->page_faults_allowed < 1) { + panic("page fault not allowed at this place. Touching address " + "%p from eip %p\n", (void *)cr2, (void *)frame->eip); + return; + } + + enable_interrupts(); + + vm_page_fault(cr2, frame->eip, + (frame->error_code & 0x2) != 0, // write access + (frame->error_code & 0x4) != 0, // userland + &newip); + if (newip != 0) { + // the page fault handler wants us to modify the iframe to set the + // IP the cpu will return to to be this ip + frame->eip = newip; + } +} + + +status_t +arch_int_init(struct kernel_args *args) +{ + int i; + interrupt_handler_function** table; + + // set the global sIDT variable + sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt; + + // setup the standard programmable interrupt controller + pic_init(); + + set_interrupt_gate(0, 0, &trap0); + set_interrupt_gate(0, 1, &trap1); + set_interrupt_gate(0, 2, &trap2); + set_trap_gate(0, 3, &trap3); + set_interrupt_gate(0, 4, &trap4); + set_interrupt_gate(0, 5, &trap5); + set_interrupt_gate(0, 6, &trap6); + set_interrupt_gate(0, 7, &trap7); + // trap8 (double fault) is set in arch_cpu.c + set_interrupt_gate(0, 9, &trap9); + set_interrupt_gate(0, 10, &trap10); + set_interrupt_gate(0, 11, &trap11); + set_interrupt_gate(0, 12, &trap12); + set_interrupt_gate(0, 13, &trap13); + set_interrupt_gate(0, 14, &trap14); +// set_interrupt_gate(0, 15, &trap15); + set_interrupt_gate(0, 16, &trap16); + set_interrupt_gate(0, 17, &trap17); + set_interrupt_gate(0, 18, &trap18); + set_interrupt_gate(0, 19, &trap19); + + // legacy or ioapic interrupts + set_interrupt_gate(0, 32, &trap32); + set_interrupt_gate(0, 33, &trap33); + set_interrupt_gate(0, 34, &trap34); + set_interrupt_gate(0, 35, &trap35); + set_interrupt_gate(0, 36, &trap36); + set_interrupt_gate(0, 37, &trap37); + set_interrupt_gate(0, 38, &trap38); + set_interrupt_gate(0, 39, &trap39); + set_interrupt_gate(0, 40, &trap40); + set_interrupt_gate(0, 41, &trap41); + set_interrupt_gate(0, 42, &trap42); + set_interrupt_gate(0, 43, &trap43); + set_interrupt_gate(0, 44, &trap44); + set_interrupt_gate(0, 45, &trap45); + set_interrupt_gate(0, 46, &trap46); + set_interrupt_gate(0, 47, &trap47); + + // additional ioapic interrupts + set_interrupt_gate(0, 48, &trap48); + set_interrupt_gate(0, 49, &trap49); + set_interrupt_gate(0, 50, &trap50); + set_interrupt_gate(0, 51, &trap51); + set_interrupt_gate(0, 52, &trap52); + set_interrupt_gate(0, 53, &trap53); + set_interrupt_gate(0, 54, &trap54); + set_interrupt_gate(0, 55, &trap55); + + // configurable msi or msi-x interrupts + set_interrupt_gate(0, 56, &trap56); + set_interrupt_gate(0, 57, &trap57); + set_interrupt_gate(0, 58, &trap58); + set_interrupt_gate(0, 59, &trap59); + set_interrupt_gate(0, 60, &trap60); + set_interrupt_gate(0, 61, &trap61); + set_interrupt_gate(0, 62, &trap62); + set_interrupt_gate(0, 63, &trap63); + set_interrupt_gate(0, 64, &trap64); + set_interrupt_gate(0, 65, &trap65); + set_interrupt_gate(0, 66, &trap66); + set_interrupt_gate(0, 67, &trap67); + set_interrupt_gate(0, 68, &trap68); + set_interrupt_gate(0, 69, &trap69); + set_interrupt_gate(0, 70, &trap70); + set_interrupt_gate(0, 71, &trap71); + set_interrupt_gate(0, 72, &trap72); + set_interrupt_gate(0, 73, &trap73); + set_interrupt_gate(0, 74, &trap74); + set_interrupt_gate(0, 75, &trap75); + set_interrupt_gate(0, 76, &trap76); + set_interrupt_gate(0, 77, &trap77); + set_interrupt_gate(0, 78, &trap78); + set_interrupt_gate(0, 79, &trap79); + set_interrupt_gate(0, 80, &trap80); + set_interrupt_gate(0, 81, &trap81); + set_interrupt_gate(0, 82, &trap82); + set_interrupt_gate(0, 83, &trap83); + set_interrupt_gate(0, 84, &trap84); + set_interrupt_gate(0, 85, &trap85); + set_interrupt_gate(0, 86, &trap86); + set_interrupt_gate(0, 87, &trap87); + set_interrupt_gate(0, 88, &trap88); + set_interrupt_gate(0, 89, &trap89); + set_interrupt_gate(0, 90, &trap90); + set_interrupt_gate(0, 91, &trap91); + set_interrupt_gate(0, 92, &trap92); + set_interrupt_gate(0, 93, &trap93); + set_interrupt_gate(0, 94, &trap94); + set_interrupt_gate(0, 95, &trap95); + set_interrupt_gate(0, 96, &trap96); + set_interrupt_gate(0, 97, &trap97); + + set_trap_gate(0, 98, &trap98); // for performance testing only + set_trap_gate(0, 99, &trap99); // syscall interrupt + + reserve_io_interrupt_vectors(2, 98); + + // configurable msi or msi-x interrupts + set_interrupt_gate(0, 100, &trap100); + set_interrupt_gate(0, 101, &trap101); + set_interrupt_gate(0, 102, &trap102); + set_interrupt_gate(0, 103, &trap103); + set_interrupt_gate(0, 104, &trap104); + set_interrupt_gate(0, 105, &trap105); + set_interrupt_gate(0, 106, &trap106); + set_interrupt_gate(0, 107, &trap107); + set_interrupt_gate(0, 108, &trap108); + set_interrupt_gate(0, 109, &trap109); + set_interrupt_gate(0, 110, &trap110); + set_interrupt_gate(0, 111, &trap111); + set_interrupt_gate(0, 112, &trap112); + set_interrupt_gate(0, 113, &trap113); + set_interrupt_gate(0, 114, &trap114); + set_interrupt_gate(0, 115, &trap115); + set_interrupt_gate(0, 116, &trap116); + set_interrupt_gate(0, 117, &trap117); + set_interrupt_gate(0, 118, &trap118); + set_interrupt_gate(0, 119, &trap119); + set_interrupt_gate(0, 120, &trap120); + set_interrupt_gate(0, 121, &trap121); + set_interrupt_gate(0, 122, &trap122); + set_interrupt_gate(0, 123, &trap123); + set_interrupt_gate(0, 124, &trap124); + set_interrupt_gate(0, 125, &trap125); + set_interrupt_gate(0, 126, &trap126); + set_interrupt_gate(0, 127, &trap127); + set_interrupt_gate(0, 128, &trap128); + set_interrupt_gate(0, 129, &trap129); + set_interrupt_gate(0, 130, &trap130); + set_interrupt_gate(0, 131, &trap131); + set_interrupt_gate(0, 132, &trap132); + set_interrupt_gate(0, 133, &trap133); + set_interrupt_gate(0, 134, &trap134); + set_interrupt_gate(0, 135, &trap135); + set_interrupt_gate(0, 136, &trap136); + set_interrupt_gate(0, 137, &trap137); + set_interrupt_gate(0, 138, &trap138); + set_interrupt_gate(0, 139, &trap139); + set_interrupt_gate(0, 140, &trap140); + set_interrupt_gate(0, 141, &trap141); + set_interrupt_gate(0, 142, &trap142); + set_interrupt_gate(0, 143, &trap143); + set_interrupt_gate(0, 144, &trap144); + set_interrupt_gate(0, 145, &trap145); + set_interrupt_gate(0, 146, &trap146); + set_interrupt_gate(0, 147, &trap147); + set_interrupt_gate(0, 148, &trap148); + set_interrupt_gate(0, 149, &trap149); + set_interrupt_gate(0, 150, &trap150); + set_interrupt_gate(0, 151, &trap151); + set_interrupt_gate(0, 152, &trap152); + set_interrupt_gate(0, 153, &trap153); + set_interrupt_gate(0, 154, &trap154); + set_interrupt_gate(0, 155, &trap155); + set_interrupt_gate(0, 156, &trap156); + set_interrupt_gate(0, 157, &trap157); + set_interrupt_gate(0, 158, &trap158); + set_interrupt_gate(0, 159, &trap159); + set_interrupt_gate(0, 160, &trap160); + set_interrupt_gate(0, 161, &trap161); + set_interrupt_gate(0, 162, &trap162); + set_interrupt_gate(0, 163, &trap163); + set_interrupt_gate(0, 164, &trap164); + set_interrupt_gate(0, 165, &trap165); + set_interrupt_gate(0, 166, &trap166); + set_interrupt_gate(0, 167, &trap167); + set_interrupt_gate(0, 168, &trap168); + set_interrupt_gate(0, 169, &trap169); + set_interrupt_gate(0, 170, &trap170); + set_interrupt_gate(0, 171, &trap171); + set_interrupt_gate(0, 172, &trap172); + set_interrupt_gate(0, 173, &trap173); + set_interrupt_gate(0, 174, &trap174); + set_interrupt_gate(0, 175, &trap175); + set_interrupt_gate(0, 176, &trap176); + set_interrupt_gate(0, 177, &trap177); + set_interrupt_gate(0, 178, &trap178); + set_interrupt_gate(0, 179, &trap179); + set_interrupt_gate(0, 180, &trap180); + set_interrupt_gate(0, 181, &trap181); + set_interrupt_gate(0, 182, &trap182); + set_interrupt_gate(0, 183, &trap183); + set_interrupt_gate(0, 184, &trap184); + set_interrupt_gate(0, 185, &trap185); + set_interrupt_gate(0, 186, &trap186); + set_interrupt_gate(0, 187, &trap187); + set_interrupt_gate(0, 188, &trap188); + set_interrupt_gate(0, 189, &trap189); + set_interrupt_gate(0, 190, &trap190); + set_interrupt_gate(0, 191, &trap191); + set_interrupt_gate(0, 192, &trap192); + set_interrupt_gate(0, 193, &trap193); + set_interrupt_gate(0, 194, &trap194); + set_interrupt_gate(0, 195, &trap195); + set_interrupt_gate(0, 196, &trap196); + set_interrupt_gate(0, 197, &trap197); + set_interrupt_gate(0, 198, &trap198); + set_interrupt_gate(0, 199, &trap199); + set_interrupt_gate(0, 200, &trap200); + set_interrupt_gate(0, 201, &trap201); + set_interrupt_gate(0, 202, &trap202); + set_interrupt_gate(0, 203, &trap203); + set_interrupt_gate(0, 204, &trap204); + set_interrupt_gate(0, 205, &trap205); + set_interrupt_gate(0, 206, &trap206); + set_interrupt_gate(0, 207, &trap207); + set_interrupt_gate(0, 208, &trap208); + set_interrupt_gate(0, 209, &trap209); + set_interrupt_gate(0, 210, &trap210); + set_interrupt_gate(0, 211, &trap211); + set_interrupt_gate(0, 212, &trap212); + set_interrupt_gate(0, 213, &trap213); + set_interrupt_gate(0, 214, &trap214); + set_interrupt_gate(0, 215, &trap215); + set_interrupt_gate(0, 216, &trap216); + set_interrupt_gate(0, 217, &trap217); + set_interrupt_gate(0, 218, &trap218); + set_interrupt_gate(0, 219, &trap219); + set_interrupt_gate(0, 220, &trap220); + set_interrupt_gate(0, 221, &trap221); + set_interrupt_gate(0, 222, &trap222); + set_interrupt_gate(0, 223, &trap223); + set_interrupt_gate(0, 224, &trap224); + set_interrupt_gate(0, 225, &trap225); + set_interrupt_gate(0, 226, &trap226); + set_interrupt_gate(0, 227, &trap227); + set_interrupt_gate(0, 228, &trap228); + set_interrupt_gate(0, 229, &trap229); + set_interrupt_gate(0, 230, &trap230); + set_interrupt_gate(0, 231, &trap231); + set_interrupt_gate(0, 232, &trap232); + set_interrupt_gate(0, 233, &trap233); + set_interrupt_gate(0, 234, &trap234); + set_interrupt_gate(0, 235, &trap235); + set_interrupt_gate(0, 236, &trap236); + set_interrupt_gate(0, 237, &trap237); + set_interrupt_gate(0, 238, &trap238); + set_interrupt_gate(0, 239, &trap239); + set_interrupt_gate(0, 240, &trap240); + set_interrupt_gate(0, 241, &trap241); + set_interrupt_gate(0, 242, &trap242); + set_interrupt_gate(0, 243, &trap243); + set_interrupt_gate(0, 244, &trap244); + set_interrupt_gate(0, 245, &trap245); + set_interrupt_gate(0, 246, &trap246); + set_interrupt_gate(0, 247, &trap247); + set_interrupt_gate(0, 248, &trap248); + set_interrupt_gate(0, 249, &trap249); + set_interrupt_gate(0, 250, &trap250); + + // smp / apic local interrupts + set_interrupt_gate(0, 251, &trap251); + set_interrupt_gate(0, 252, &trap252); + set_interrupt_gate(0, 253, &trap253); + set_interrupt_gate(0, 254, &trap254); + set_interrupt_gate(0, 255, &trap255); + + // init interrupt handler table + table = gInterruptHandlerTable; + + // defaults + for (i = 0; i < ARCH_INTERRUPT_BASE; i++) + table[i] = invalid_exception; + for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) + table[i] = hardware_interrupt; + + table[0] = unexpected_exception; // Divide Error Exception (#DE) + table[1] = x86_handle_debug_exception; // Debug Exception (#DB) + table[2] = fatal_exception; // NMI Interrupt + table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) + table[4] = unexpected_exception; // Overflow Exception (#OF) + table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = fatal_exception; // Device Not Available Exception (#NM) + table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) + table[9] = fatal_exception; // Coprocessor Segment Overrun + table[10] = fatal_exception; // Invalid TSS Exception (#TS) + table[11] = fatal_exception; // Segment Not Present (#NP) + table[12] = fatal_exception; // Stack Fault Exception (#SS) + table[13] = unexpected_exception; // General Protection Exception (#GP) + table[14] = page_fault_exception; // Page-Fault Exception (#PF) + table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = unexpected_exception; // Alignment Check Exception (#AC) + table[18] = fatal_exception; // Machine-Check Exception (#MC) + table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + + return B_OK; +} + + +status_t +arch_int_init_post_vm(struct kernel_args *args) +{ + // Always init the local apic as it can be used for timers even if we + // don't end up using the io apic + apic_init(args); + + // create IDT area for the boot CPU + area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, + B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + if (area < 0) + return area; + + // create IDTs for the off-boot CPU + size_t idtSize = 256 * 8; + // 256 8 bytes-sized descriptors + int32 cpuCount = smp_get_num_cpus(); + if (cpuCount > 0) { + size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE); + desc_table* idt; + virtual_address_restrictions virtualRestrictions = {}; + virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; + physical_address_restrictions physicalRestrictions = {}; + area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS, + B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, + &virtualRestrictions, &physicalRestrictions, (void**)&idt); + if (area < 0) + return area; + + for (int32 i = 1; i < cpuCount; i++) { + sIDTs[i] = idt; + memcpy(idt, sIDTs[0], idtSize); + idt += 256; + // The CPU's IDTR will be set in arch_cpu_init_percpu(). + } + } + + return area >= B_OK ? B_OK : area; +} diff --git a/src/system/kernel/arch/x86/arch_interrupts.S b/src/system/kernel/arch/x86/32/interrupts.S similarity index 100% rename from src/system/kernel/arch/x86/arch_interrupts.S rename to src/system/kernel/arch/x86/32/interrupts.S diff --git a/src/system/kernel/arch/x86/interrupts.h b/src/system/kernel/arch/x86/32/interrupts.h similarity index 100% rename from src/system/kernel/arch/x86/interrupts.h rename to src/system/kernel/arch/x86/32/interrupts.h diff --git a/src/system/kernel/arch/x86_64/arch_int.cpp b/src/system/kernel/arch/x86/64/int.cpp similarity index 90% rename from src/system/kernel/arch/x86_64/arch_int.cpp rename to src/system/kernel/arch/x86/64/int.cpp index dcab07ec0d..d9f3a0a76a 100644 --- a/src/system/kernel/arch/x86_64/arch_int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -12,11 +12,14 @@ #include #include -#include +#include +#include +#include typedef void interrupt_handler_function(iframe* frame); + static const char* kInterruptNames[] = { /* 0 */ "Divide Error Exception", /* 1 */ "Debug Exception", @@ -46,6 +49,7 @@ static interrupt_descriptor* sIDT; interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; extern uint8 isr_array[kInterruptHandlerTableSize][16]; +extern void hardware_interrupt(struct iframe* frame); static const char* @@ -104,27 +108,6 @@ page_fault_exception(iframe* frame) // #pragma mark - -void -arch_int_enable_io_interrupt(int irq) -{ - -} - - -void -arch_int_disable_io_interrupt(int irq) -{ - -} - - -void -arch_int_configure_io_interrupt(int irq, uint32 config) -{ - -} - - status_t arch_int_init(kernel_args* args) { @@ -152,8 +135,8 @@ arch_int_init(kernel_args* args) // Initialize the interrupt handler table. for (uint32 i = 0; i < ARCH_INTERRUPT_BASE; i++) table[i] = invalid_exception; - //for (uint32 i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) - // table[i] = hardware_interrupt; + for (uint32 i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++) + table[i] = hardware_interrupt; table[0] = unexpected_exception; // Divide Error Exception (#DE) //table[1] = x86_handle_debug_exception; // Debug Exception (#DB) @@ -165,7 +148,7 @@ arch_int_init(kernel_args* args) table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = fatal_exception; // Double Fault Exception (#DF) + table[8] = fatal_exception; // Double Fault Exception (#DF) table[9] = fatal_exception; // Coprocessor Segment Overrun table[10] = fatal_exception; // Invalid TSS Exception (#TS) table[11] = fatal_exception; // Segment Not Present (#NP) @@ -184,6 +167,9 @@ arch_int_init(kernel_args* args) }; asm volatile("lidt %0" :: "m"(idtr)); + // Set up the legacy PIC. + pic_init(); + panic("not implemented\n"); return B_OK; } @@ -192,19 +178,11 @@ arch_int_init(kernel_args* args) status_t arch_int_init_post_vm(kernel_args* args) { - return B_OK; -} - - -status_t -arch_int_init_io(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_int_init_post_device_manager(kernel_args* args) -{ + // Always init the local apic as it can be used for timers even if we + // don't end up using the io apic + //apic_init(args); + + // TODO: create area for IDT. + return B_OK; } diff --git a/src/system/kernel/arch/x86_64/arch_interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S similarity index 97% rename from src/system/kernel/arch/x86_64/arch_interrupts.S rename to src/system/kernel/arch/x86/64/interrupts.S index 908a2d4940..d5f8fcad30 100644 --- a/src/system/kernel/arch/x86_64/arch_interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -6,8 +6,8 @@ #include -#include -#include +#include +#include #include "asm_offsets.h" diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index d0cde670e7..299c6fc648 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -35,7 +34,6 @@ #include #include #include -#include #include @@ -677,55 +675,6 @@ arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, } -void -arch_int_enable_io_interrupt(int irq) -{ - -} - - -void -arch_int_disable_io_interrupt(int irq) -{ - -} - - -void -arch_int_configure_io_interrupt(int irq, uint32 config) -{ - -} - - -status_t -arch_int_init(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_int_init_post_vm(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_int_init_io(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_int_init_post_device_manager(struct kernel_args *args) -{ - return B_OK; -} - - // Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. status_t diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 60ec7ccd9a..b0d08957c8 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -20,17 +20,21 @@ if $(TARGET_ARCH) = x86_64 { SEARCH_SOURCE += [ FDirName $(SUBDIR) 64 ] ; archSpecificSources = + int.cpp + interrupts.S stubs.cpp ; } else { SEARCH_SOURCE += [ FDirName $(SUBDIR) 32 ] ; archSpecificSources = + int.cpp + interrupts.S + arch_commpage.cpp arch_cpu.cpp arch_debug.cpp arch_elf.cpp - arch_int.cpp arch_platform.cpp # arch_selector.cpp arch_real_time_clock.cpp @@ -40,7 +44,6 @@ if $(TARGET_ARCH) = x86_64 { arch_vm.cpp arch_vm_translation_map.cpp arch_x86.S - arch_interrupts.S arch_system_info.cpp arch_user_debugger.cpp apic.cpp @@ -50,7 +53,6 @@ if $(TARGET_ARCH) = x86_64 { ioapic.cpp irq_routing_table.cpp msi.cpp - pic.cpp syscall.S vm86.cpp x86_signals.cpp @@ -83,6 +85,8 @@ if $(TARGET_ARCH) = x86_64 { local archGenericSources = arch_debug_console.cpp + arch_int.cpp + pic.cpp ; KernelMergeObject kernel_arch_x86.o : diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index ace0767439..9bec1d7743 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -13,26 +13,16 @@ #include #include #include -#include -#include #include #include #include -#include -#include #include #include -#include -#include -#include #include #include #include -#include - -#include "interrupts.h" #include @@ -49,107 +39,58 @@ #endif -static const interrupt_controller *sCurrentPIC = NULL; - -static const char *kInterruptNames[] = { - /* 0 */ "Divide Error Exception", - /* 1 */ "Debug Exception", - /* 2 */ "NMI Interrupt", - /* 3 */ "Breakpoint Exception", - /* 4 */ "Overflow Exception", - /* 5 */ "BOUND Range Exceeded Exception", - /* 6 */ "Invalid Opcode Exception", - /* 7 */ "Device Not Available Exception", - /* 8 */ "Double Fault Exception", - /* 9 */ "Coprocessor Segment Overrun", - /* 10 */ "Invalid TSS Exception", - /* 11 */ "Segment Not Present", - /* 12 */ "Stack Fault Exception", - /* 13 */ "General Protection Exception", - /* 14 */ "Page-Fault Exception", - /* 15 */ "-", - /* 16 */ "x87 FPU Floating-Point Error", - /* 17 */ "Alignment Check Exception", - /* 18 */ "Machine-Check Exception", - /* 19 */ "SIMD Floating-Point Exception", -}; -static const int kInterruptNameCount = 20; - -#define MAX_ARGS 16 - -typedef struct { - uint32 a, b; -} desc_table; -static desc_table* sIDTs[B_MAX_CPU_COUNT]; - -// table with functions handling respective interrupts -typedef void interrupt_handler_function(struct iframe* frame); - -#define INTERRUPT_HANDLER_TABLE_SIZE 256 -interrupt_handler_function* gInterruptHandlerTable[ - INTERRUPT_HANDLER_TABLE_SIZE]; +static const interrupt_controller* sCurrentPIC = NULL; -/*! Initializes a descriptor in an IDT. -*/ -static void -set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl) -{ - unsigned int gate1; // first byte of gate desc - unsigned int gate2; // second byte of gate desc - - gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); - gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); - - gate_addr->a = gate1; - gate_addr->b = gate2; -} - - -/*! Initializes the descriptor for interrupt vector \a n in the IDT of the - specified CPU to an interrupt-gate descriptor with the given procedure - address. - For CPUs other than the boot CPU it must not be called before - arch_int_init_post_vm(). -*/ -static void -set_interrupt_gate(int32 cpu, int n, void (*addr)()) -{ - set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL); -} - - -/*! Initializes the descriptor for interrupt vector \a n in the IDT of the - specified CPU to an trap-gate descriptor with the given procedure address. - For CPUs other than the boot CPU it must not be called before - arch_int_init_post_vm(). -*/ -static void -set_trap_gate(int32 cpu, int n, void (*addr)()) -{ - set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER); -} - - -/*! Initializes the descriptor for interrupt vector \a n in the IDT of CPU - \a cpu to a task-gate descripter referring to the TSS segment identified - by TSS segment selector \a segment. - For CPUs other than the boot CPU it must not be called before - arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine). -*/ void -x86_set_task_gate(int32 cpu, int32 n, int32 segment) +hardware_interrupt(struct iframe* frame) { - sIDTs[cpu][n].a = (segment << 16); - sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5 -} +#ifndef __x86_64__ + int32 vector = frame->vector - ARCH_INTERRUPT_BASE; + bool levelTriggered = false; + Thread* thread = thread_get_current_thread(); + if (sCurrentPIC->is_spurious_interrupt(vector)) { + TRACE(("got spurious interrupt at vector %ld\n", vector)); + return; + } -/*! Returns the virtual IDT address for CPU \a cpu. */ -void* -x86_get_idt(int32 cpu) -{ - return sIDTs[cpu]; + levelTriggered = sCurrentPIC->is_level_triggered_interrupt(vector); + + if (!levelTriggered) { + // if it's not handled by the current pic then it's an apic generated + // interrupt like local interrupts, msi or ipi. + if (!sCurrentPIC->end_of_interrupt(vector)) + apic_end_of_interrupt(); + } + + int_io_interrupt_handler(vector, levelTriggered); + + if (levelTriggered) { + if (!sCurrentPIC->end_of_interrupt(vector)) + apic_end_of_interrupt(); + } + + cpu_status state = disable_interrupts(); + if (thread->cpu->invoke_scheduler) { + SpinLocker schedulerLocker(gSchedulerLock); + scheduler_reschedule(); + schedulerLocker.Unlock(); + restore_interrupts(state); + } else if (thread->post_interrupt_callback != NULL) { + void (*callback)(void*) = thread->post_interrupt_callback; + void* data = thread->post_interrupt_data; + + thread->post_interrupt_callback = NULL; + thread->post_interrupt_data = NULL; + + restore_interrupts(state); + + callback(data); + } +#else + panic("implement me"); +#endif } @@ -211,703 +152,28 @@ arch_int_are_interrupts_enabled(void) } -static const char * -exception_name(int number, char *buffer, int32 bufferSize) -{ - if (number >= 0 && number < kInterruptNameCount) - return kInterruptNames[number]; - - snprintf(buffer, bufferSize, "exception %d", number); - return buffer; -} - - -static void -invalid_exception(struct iframe* frame) -{ - Thread* thread = thread_get_current_thread(); - char name[32]; - panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->eip, thread ? thread->id : -1); -} - - -static void -fatal_exception(struct iframe *frame) -{ - char name[32]; - panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), frame->error_code); -} - - -static void -unexpected_exception(struct iframe* frame) -{ - debug_exception_type type; - uint32 signalNumber; - int32 signalCode; - addr_t signalAddress = 0; - int32 signalError = B_ERROR; - - if (IFRAME_IS_VM86(frame)) { - x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? - B_OK : B_ERROR); - // won't get here - } - - switch (frame->vector) { - case 0: // Divide Error Exception (#DE) - type = B_DIVIDE_ERROR; - signalNumber = SIGFPE; - signalCode = FPE_INTDIV; - signalAddress = frame->eip; - break; - - case 4: // Overflow Exception (#OF) - type = B_OVERFLOW_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_INTOVF; - signalAddress = frame->eip; - break; - - case 5: // BOUND Range Exceeded Exception (#BR) - type = B_BOUNDS_CHECK_EXCEPTION; - signalNumber = SIGTRAP; - signalCode = SI_USER; - break; - - case 6: // Invalid Opcode Exception (#UD) - type = B_INVALID_OPCODE_EXCEPTION; - signalNumber = SIGILL; - signalCode = ILL_ILLOPC; - signalAddress = frame->eip; - break; - - case 13: // General Protection Exception (#GP) - type = B_GENERAL_PROTECTION_FAULT; - signalNumber = SIGILL; - signalCode = ILL_PRVOPC; // or ILL_PRVREG - signalAddress = frame->eip; - break; - - case 16: // x87 FPU Floating-Point Error (#MF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the FPU status - // register! - signalAddress = frame->eip; - break; - - case 17: // Alignment Check Exception (#AC) - type = B_ALIGNMENT_EXCEPTION; - signalNumber = SIGBUS; - signalCode = BUS_ADRALN; - // TODO: Also get the address (from where?). Since we don't enable - // alignment checking this exception should never happen, though. - signalError = EFAULT; - break; - - case 19: // SIMD Floating-Point Exception (#XF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the MXCSR register! - signalAddress = frame->eip; - break; - - default: - invalid_exception(frame); - return; - } - - if (IFRAME_IS_USER(frame)) { - struct sigaction action; - Thread* thread = thread_get_current_thread(); - - enable_interrupts(); - - // If the thread has a signal handler for the signal, we simply send it - // the signal. Otherwise we notify the user debugger first. - if ((sigaction(signalNumber, NULL, &action) == 0 - && action.sa_handler != SIG_DFL - && action.sa_handler != SIG_IGN) - || user_debug_exception_occurred(type, signalNumber)) { - Signal signal(signalNumber, signalCode, signalError, - thread->team->id); - signal.SetAddress((void*)signalAddress); - send_signal_to_thread(thread, signal, 0); - } - } else { - char name[32]; - panic("Unexpected exception \"%s\" occurred in kernel mode! " - "Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), - frame->error_code); - } -} - - -void -x86_double_fault_exception(struct iframe* frame) -{ - int cpu = x86_double_fault_get_cpu(); - - // The double fault iframe contains no useful information (as - // per Intel's architecture spec). Thus we simply save the - // information from the (unhandlable) exception which caused the - // double in our iframe. This will result even in useful stack - // traces. Only problem is that we trust that at least the - // TSS is still accessible. - struct tss *tss = &gCPU[cpu].arch.tss; - - frame->cs = tss->cs; - frame->es = tss->es; - frame->ds = tss->ds; - frame->fs = tss->fs; - frame->gs = tss->gs; - frame->eip = tss->eip; - frame->ebp = tss->ebp; - frame->esp = tss->esp; - frame->eax = tss->eax; - frame->ebx = tss->ebx; - frame->ecx = tss->ecx; - frame->edx = tss->edx; - frame->esi = tss->esi; - frame->edi = tss->edi; - frame->flags = tss->eflags; - - // Use a special handler for page faults which avoids the triple fault - // pitfalls. - set_interrupt_gate(cpu, 14, &trap14_double_fault); - - debug_double_fault(cpu); -} - - -void -x86_page_fault_exception_double_fault(struct iframe* frame) -{ - uint32 cr2; - asm("movl %%cr2, %0" : "=r" (cr2)); - - // Only if this CPU has a fault handler, we're allowed to be here. - cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; - addr_t faultHandler = cpu.fault_handler; - if (faultHandler != 0) { - debug_set_page_fault_info(cr2, frame->eip, - (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = faultHandler; - frame->ebp = cpu.fault_handler_stack_pointer; - return; - } - - // No fault handler. This is bad. Since we originally came from a double - // fault, we don't try to reenter the kernel debugger. Instead we just - // print the info we've got and enter an infinite loop. - kprintf("Page fault in double fault debugger without fault handler! " - "Touching address %p from eip %p. Entering infinite loop...\n", - (void*)cr2, (void*)frame->eip); - - while (true); -} - - -static void -page_fault_exception(struct iframe* frame) -{ - Thread *thread = thread_get_current_thread(); - uint32 cr2; - addr_t newip; - - asm("movl %%cr2, %0" : "=r" (cr2)); - - if (debug_debugger_running()) { - // If this CPU or this thread has a fault handler, we're allowed to be - // here. - if (thread != NULL) { - cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; - if (cpu->fault_handler != 0) { - debug_set_page_fault_info(cr2, frame->eip, - (frame->error_code & 0x2) != 0 - ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = cpu->fault_handler; - frame->ebp = cpu->fault_handler_stack_pointer; - return; - } - - if (thread->fault_handler != 0) { - kprintf("ERROR: thread::fault_handler used in kernel " - "debugger!\n"); - debug_set_page_fault_info(cr2, frame->eip, - (frame->error_code & 0x2) != 0 - ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = thread->fault_handler; - return; - } - } - - // otherwise, not really - panic("page fault in debugger without fault handler! Touching " - "address %p from eip %p\n", (void *)cr2, (void *)frame->eip); - return; - } else if ((frame->flags & 0x200) == 0) { - // interrupts disabled - - // If a page fault handler is installed, we're allowed to be here. - // TODO: Now we are generally allowing user_memcpy() with interrupts - // disabled, which in most cases is a bug. We should add some thread - // flag allowing to explicitly indicate that this handling is desired. - if (thread && thread->fault_handler != 0) { - if (frame->eip != thread->fault_handler) { - frame->eip = thread->fault_handler; - return; - } - - // The fault happened at the fault handler address. This is a - // certain infinite loop. - panic("page fault, interrupts disabled, fault handler loop. " - "Touching address %p from eip %p\n", (void*)cr2, - (void*)frame->eip); - } - - // If we are not running the kernel startup the page fault was not - // allowed to happen and we must panic. - panic("page fault, but interrupts were disabled. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->eip); - return; - } else if (thread != NULL && thread->page_faults_allowed < 1) { - panic("page fault not allowed at this place. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->eip); - return; - } - - enable_interrupts(); - - vm_page_fault(cr2, frame->eip, - (frame->error_code & 0x2) != 0, // write access - (frame->error_code & 0x4) != 0, // userland - &newip); - if (newip != 0) { - // the page fault handler wants us to modify the iframe to set the - // IP the cpu will return to to be this ip - frame->eip = newip; - } -} - - -static void -hardware_interrupt(struct iframe* frame) -{ - int32 vector = frame->vector - ARCH_INTERRUPT_BASE; - bool levelTriggered = false; - Thread* thread = thread_get_current_thread(); - - if (sCurrentPIC->is_spurious_interrupt(vector)) { - TRACE(("got spurious interrupt at vector %ld\n", vector)); - return; - } - - levelTriggered = sCurrentPIC->is_level_triggered_interrupt(vector); - - if (!levelTriggered) { - // if it's not handled by the current pic then it's an apic generated - // interrupt like local interrupts, msi or ipi. - if (!sCurrentPIC->end_of_interrupt(vector)) - apic_end_of_interrupt(); - } - - int_io_interrupt_handler(vector, levelTriggered); - - if (levelTriggered) { - if (!sCurrentPIC->end_of_interrupt(vector)) - apic_end_of_interrupt(); - } - - cpu_status state = disable_interrupts(); - if (thread->cpu->invoke_scheduler) { - SpinLocker schedulerLocker(gSchedulerLock); - scheduler_reschedule(); - schedulerLocker.Unlock(); - restore_interrupts(state); - } else if (thread->post_interrupt_callback != NULL) { - void (*callback)(void*) = thread->post_interrupt_callback; - void* data = thread->post_interrupt_data; - - thread->post_interrupt_callback = NULL; - thread->post_interrupt_data = NULL; - - restore_interrupts(state); - - callback(data); - } -} - - -status_t -arch_int_init(struct kernel_args *args) -{ - int i; - interrupt_handler_function** table; - - // set the global sIDT variable - sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt; - - // setup the standard programmable interrupt controller - pic_init(); - - set_interrupt_gate(0, 0, &trap0); - set_interrupt_gate(0, 1, &trap1); - set_interrupt_gate(0, 2, &trap2); - set_trap_gate(0, 3, &trap3); - set_interrupt_gate(0, 4, &trap4); - set_interrupt_gate(0, 5, &trap5); - set_interrupt_gate(0, 6, &trap6); - set_interrupt_gate(0, 7, &trap7); - // trap8 (double fault) is set in arch_cpu.c - set_interrupt_gate(0, 9, &trap9); - set_interrupt_gate(0, 10, &trap10); - set_interrupt_gate(0, 11, &trap11); - set_interrupt_gate(0, 12, &trap12); - set_interrupt_gate(0, 13, &trap13); - set_interrupt_gate(0, 14, &trap14); -// set_interrupt_gate(0, 15, &trap15); - set_interrupt_gate(0, 16, &trap16); - set_interrupt_gate(0, 17, &trap17); - set_interrupt_gate(0, 18, &trap18); - set_interrupt_gate(0, 19, &trap19); - - // legacy or ioapic interrupts - set_interrupt_gate(0, 32, &trap32); - set_interrupt_gate(0, 33, &trap33); - set_interrupt_gate(0, 34, &trap34); - set_interrupt_gate(0, 35, &trap35); - set_interrupt_gate(0, 36, &trap36); - set_interrupt_gate(0, 37, &trap37); - set_interrupt_gate(0, 38, &trap38); - set_interrupt_gate(0, 39, &trap39); - set_interrupt_gate(0, 40, &trap40); - set_interrupt_gate(0, 41, &trap41); - set_interrupt_gate(0, 42, &trap42); - set_interrupt_gate(0, 43, &trap43); - set_interrupt_gate(0, 44, &trap44); - set_interrupt_gate(0, 45, &trap45); - set_interrupt_gate(0, 46, &trap46); - set_interrupt_gate(0, 47, &trap47); - - // additional ioapic interrupts - set_interrupt_gate(0, 48, &trap48); - set_interrupt_gate(0, 49, &trap49); - set_interrupt_gate(0, 50, &trap50); - set_interrupt_gate(0, 51, &trap51); - set_interrupt_gate(0, 52, &trap52); - set_interrupt_gate(0, 53, &trap53); - set_interrupt_gate(0, 54, &trap54); - set_interrupt_gate(0, 55, &trap55); - - // configurable msi or msi-x interrupts - set_interrupt_gate(0, 56, &trap56); - set_interrupt_gate(0, 57, &trap57); - set_interrupt_gate(0, 58, &trap58); - set_interrupt_gate(0, 59, &trap59); - set_interrupt_gate(0, 60, &trap60); - set_interrupt_gate(0, 61, &trap61); - set_interrupt_gate(0, 62, &trap62); - set_interrupt_gate(0, 63, &trap63); - set_interrupt_gate(0, 64, &trap64); - set_interrupt_gate(0, 65, &trap65); - set_interrupt_gate(0, 66, &trap66); - set_interrupt_gate(0, 67, &trap67); - set_interrupt_gate(0, 68, &trap68); - set_interrupt_gate(0, 69, &trap69); - set_interrupt_gate(0, 70, &trap70); - set_interrupt_gate(0, 71, &trap71); - set_interrupt_gate(0, 72, &trap72); - set_interrupt_gate(0, 73, &trap73); - set_interrupt_gate(0, 74, &trap74); - set_interrupt_gate(0, 75, &trap75); - set_interrupt_gate(0, 76, &trap76); - set_interrupt_gate(0, 77, &trap77); - set_interrupt_gate(0, 78, &trap78); - set_interrupt_gate(0, 79, &trap79); - set_interrupt_gate(0, 80, &trap80); - set_interrupt_gate(0, 81, &trap81); - set_interrupt_gate(0, 82, &trap82); - set_interrupt_gate(0, 83, &trap83); - set_interrupt_gate(0, 84, &trap84); - set_interrupt_gate(0, 85, &trap85); - set_interrupt_gate(0, 86, &trap86); - set_interrupt_gate(0, 87, &trap87); - set_interrupt_gate(0, 88, &trap88); - set_interrupt_gate(0, 89, &trap89); - set_interrupt_gate(0, 90, &trap90); - set_interrupt_gate(0, 91, &trap91); - set_interrupt_gate(0, 92, &trap92); - set_interrupt_gate(0, 93, &trap93); - set_interrupt_gate(0, 94, &trap94); - set_interrupt_gate(0, 95, &trap95); - set_interrupt_gate(0, 96, &trap96); - set_interrupt_gate(0, 97, &trap97); - - set_trap_gate(0, 98, &trap98); // for performance testing only - set_trap_gate(0, 99, &trap99); // syscall interrupt - - reserve_io_interrupt_vectors(2, 98); - - // configurable msi or msi-x interrupts - set_interrupt_gate(0, 100, &trap100); - set_interrupt_gate(0, 101, &trap101); - set_interrupt_gate(0, 102, &trap102); - set_interrupt_gate(0, 103, &trap103); - set_interrupt_gate(0, 104, &trap104); - set_interrupt_gate(0, 105, &trap105); - set_interrupt_gate(0, 106, &trap106); - set_interrupt_gate(0, 107, &trap107); - set_interrupt_gate(0, 108, &trap108); - set_interrupt_gate(0, 109, &trap109); - set_interrupt_gate(0, 110, &trap110); - set_interrupt_gate(0, 111, &trap111); - set_interrupt_gate(0, 112, &trap112); - set_interrupt_gate(0, 113, &trap113); - set_interrupt_gate(0, 114, &trap114); - set_interrupt_gate(0, 115, &trap115); - set_interrupt_gate(0, 116, &trap116); - set_interrupt_gate(0, 117, &trap117); - set_interrupt_gate(0, 118, &trap118); - set_interrupt_gate(0, 119, &trap119); - set_interrupt_gate(0, 120, &trap120); - set_interrupt_gate(0, 121, &trap121); - set_interrupt_gate(0, 122, &trap122); - set_interrupt_gate(0, 123, &trap123); - set_interrupt_gate(0, 124, &trap124); - set_interrupt_gate(0, 125, &trap125); - set_interrupt_gate(0, 126, &trap126); - set_interrupt_gate(0, 127, &trap127); - set_interrupt_gate(0, 128, &trap128); - set_interrupt_gate(0, 129, &trap129); - set_interrupt_gate(0, 130, &trap130); - set_interrupt_gate(0, 131, &trap131); - set_interrupt_gate(0, 132, &trap132); - set_interrupt_gate(0, 133, &trap133); - set_interrupt_gate(0, 134, &trap134); - set_interrupt_gate(0, 135, &trap135); - set_interrupt_gate(0, 136, &trap136); - set_interrupt_gate(0, 137, &trap137); - set_interrupt_gate(0, 138, &trap138); - set_interrupt_gate(0, 139, &trap139); - set_interrupt_gate(0, 140, &trap140); - set_interrupt_gate(0, 141, &trap141); - set_interrupt_gate(0, 142, &trap142); - set_interrupt_gate(0, 143, &trap143); - set_interrupt_gate(0, 144, &trap144); - set_interrupt_gate(0, 145, &trap145); - set_interrupt_gate(0, 146, &trap146); - set_interrupt_gate(0, 147, &trap147); - set_interrupt_gate(0, 148, &trap148); - set_interrupt_gate(0, 149, &trap149); - set_interrupt_gate(0, 150, &trap150); - set_interrupt_gate(0, 151, &trap151); - set_interrupt_gate(0, 152, &trap152); - set_interrupt_gate(0, 153, &trap153); - set_interrupt_gate(0, 154, &trap154); - set_interrupt_gate(0, 155, &trap155); - set_interrupt_gate(0, 156, &trap156); - set_interrupt_gate(0, 157, &trap157); - set_interrupt_gate(0, 158, &trap158); - set_interrupt_gate(0, 159, &trap159); - set_interrupt_gate(0, 160, &trap160); - set_interrupt_gate(0, 161, &trap161); - set_interrupt_gate(0, 162, &trap162); - set_interrupt_gate(0, 163, &trap163); - set_interrupt_gate(0, 164, &trap164); - set_interrupt_gate(0, 165, &trap165); - set_interrupt_gate(0, 166, &trap166); - set_interrupt_gate(0, 167, &trap167); - set_interrupt_gate(0, 168, &trap168); - set_interrupt_gate(0, 169, &trap169); - set_interrupt_gate(0, 170, &trap170); - set_interrupt_gate(0, 171, &trap171); - set_interrupt_gate(0, 172, &trap172); - set_interrupt_gate(0, 173, &trap173); - set_interrupt_gate(0, 174, &trap174); - set_interrupt_gate(0, 175, &trap175); - set_interrupt_gate(0, 176, &trap176); - set_interrupt_gate(0, 177, &trap177); - set_interrupt_gate(0, 178, &trap178); - set_interrupt_gate(0, 179, &trap179); - set_interrupt_gate(0, 180, &trap180); - set_interrupt_gate(0, 181, &trap181); - set_interrupt_gate(0, 182, &trap182); - set_interrupt_gate(0, 183, &trap183); - set_interrupt_gate(0, 184, &trap184); - set_interrupt_gate(0, 185, &trap185); - set_interrupt_gate(0, 186, &trap186); - set_interrupt_gate(0, 187, &trap187); - set_interrupt_gate(0, 188, &trap188); - set_interrupt_gate(0, 189, &trap189); - set_interrupt_gate(0, 190, &trap190); - set_interrupt_gate(0, 191, &trap191); - set_interrupt_gate(0, 192, &trap192); - set_interrupt_gate(0, 193, &trap193); - set_interrupt_gate(0, 194, &trap194); - set_interrupt_gate(0, 195, &trap195); - set_interrupt_gate(0, 196, &trap196); - set_interrupt_gate(0, 197, &trap197); - set_interrupt_gate(0, 198, &trap198); - set_interrupt_gate(0, 199, &trap199); - set_interrupt_gate(0, 200, &trap200); - set_interrupt_gate(0, 201, &trap201); - set_interrupt_gate(0, 202, &trap202); - set_interrupt_gate(0, 203, &trap203); - set_interrupt_gate(0, 204, &trap204); - set_interrupt_gate(0, 205, &trap205); - set_interrupt_gate(0, 206, &trap206); - set_interrupt_gate(0, 207, &trap207); - set_interrupt_gate(0, 208, &trap208); - set_interrupt_gate(0, 209, &trap209); - set_interrupt_gate(0, 210, &trap210); - set_interrupt_gate(0, 211, &trap211); - set_interrupt_gate(0, 212, &trap212); - set_interrupt_gate(0, 213, &trap213); - set_interrupt_gate(0, 214, &trap214); - set_interrupt_gate(0, 215, &trap215); - set_interrupt_gate(0, 216, &trap216); - set_interrupt_gate(0, 217, &trap217); - set_interrupt_gate(0, 218, &trap218); - set_interrupt_gate(0, 219, &trap219); - set_interrupt_gate(0, 220, &trap220); - set_interrupt_gate(0, 221, &trap221); - set_interrupt_gate(0, 222, &trap222); - set_interrupt_gate(0, 223, &trap223); - set_interrupt_gate(0, 224, &trap224); - set_interrupt_gate(0, 225, &trap225); - set_interrupt_gate(0, 226, &trap226); - set_interrupt_gate(0, 227, &trap227); - set_interrupt_gate(0, 228, &trap228); - set_interrupt_gate(0, 229, &trap229); - set_interrupt_gate(0, 230, &trap230); - set_interrupt_gate(0, 231, &trap231); - set_interrupt_gate(0, 232, &trap232); - set_interrupt_gate(0, 233, &trap233); - set_interrupt_gate(0, 234, &trap234); - set_interrupt_gate(0, 235, &trap235); - set_interrupt_gate(0, 236, &trap236); - set_interrupt_gate(0, 237, &trap237); - set_interrupt_gate(0, 238, &trap238); - set_interrupt_gate(0, 239, &trap239); - set_interrupt_gate(0, 240, &trap240); - set_interrupt_gate(0, 241, &trap241); - set_interrupt_gate(0, 242, &trap242); - set_interrupt_gate(0, 243, &trap243); - set_interrupt_gate(0, 244, &trap244); - set_interrupt_gate(0, 245, &trap245); - set_interrupt_gate(0, 246, &trap246); - set_interrupt_gate(0, 247, &trap247); - set_interrupt_gate(0, 248, &trap248); - set_interrupt_gate(0, 249, &trap249); - set_interrupt_gate(0, 250, &trap250); - - // smp / apic local interrupts - set_interrupt_gate(0, 251, &trap251); - set_interrupt_gate(0, 252, &trap252); - set_interrupt_gate(0, 253, &trap253); - set_interrupt_gate(0, 254, &trap254); - set_interrupt_gate(0, 255, &trap255); - - // init interrupt handler table - table = gInterruptHandlerTable; - - // defaults - for (i = 0; i < ARCH_INTERRUPT_BASE; i++) - table[i] = invalid_exception; - for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) - table[i] = hardware_interrupt; - - table[0] = unexpected_exception; // Divide Error Exception (#DE) - table[1] = x86_handle_debug_exception; // Debug Exception (#DB) - table[2] = fatal_exception; // NMI Interrupt - table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) - table[4] = unexpected_exception; // Overflow Exception (#OF) - table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) - table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) - table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) - table[9] = fatal_exception; // Coprocessor Segment Overrun - table[10] = fatal_exception; // Invalid TSS Exception (#TS) - table[11] = fatal_exception; // Segment Not Present (#NP) - table[12] = fatal_exception; // Stack Fault Exception (#SS) - table[13] = unexpected_exception; // General Protection Exception (#GP) - table[14] = page_fault_exception; // Page-Fault Exception (#PF) - table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) - table[17] = unexpected_exception; // Alignment Check Exception (#AC) - table[18] = fatal_exception; // Machine-Check Exception (#MC) - table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) - - return B_OK; -} - - -status_t -arch_int_init_post_vm(struct kernel_args *args) -{ - // Always init the local apic as it can be used for timers even if we - // don't end up using the io apic - apic_init(args); - - // create IDT area for the boot CPU - area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, - B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - if (area < 0) - return area; - - // create IDTs for the off-boot CPU - size_t idtSize = 256 * 8; - // 256 8 bytes-sized descriptors - int32 cpuCount = smp_get_num_cpus(); - if (cpuCount > 0) { - size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE); - desc_table* idt; - virtual_address_restrictions virtualRestrictions = {}; - virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; - physical_address_restrictions physicalRestrictions = {}; - area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS, - B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, - &virtualRestrictions, &physicalRestrictions, (void**)&idt); - if (area < 0) - return area; - - for (int32 i = 1; i < cpuCount; i++) { - sIDTs[i] = idt; - memcpy(idt, sIDTs[0], idtSize); - idt += 256; - // The CPU's IDTR will be set in arch_cpu_init_percpu(). - } - } - - return area >= B_OK ? B_OK : area; -} - - status_t arch_int_init_io(kernel_args* args) { +#ifndef __x86_64__ ioapic_init(args); msi_init(); +#else + panic("implement me"); +#endif return B_OK; } status_t -arch_int_init_post_device_manager(struct kernel_args *args) +arch_int_init_post_device_manager(kernel_args* args) { return B_OK; } void -arch_int_set_interrupt_controller(const interrupt_controller &controller) +arch_int_set_interrupt_controller(const interrupt_controller& controller) { sCurrentPIC = &controller; } diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index b38f803ae4..679f852a60 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -44,6 +44,11 @@ dummy() DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top); DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); +#ifdef __x86_64__ + // struct iframe + DEFINE_SIZEOF_MACRO(IFRAME, iframe); + DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); +#else // struct iframe DEFINE_SIZEOF_MACRO(IFRAME, iframe); DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); @@ -58,6 +63,7 @@ dummy() // struct vm86_iframe DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); DEFINE_OFFSET_MACRO(VM86_IFRAME, vm86_iframe, flags); +#endif // struct syscall_info DEFINE_SIZEOF_MACRO(SYSCALL_INFO, syscall_info); From c005e747ef9ea6ba091c72e3fa56f8318a4bf893 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 3 Jul 2012 11:17:56 +0100 Subject: [PATCH 058/273] Removed the x86_64 headers/source directories, now all merged with x86. --- headers/private/kernel/arch/x86_64/arch_cpu.h | 102 -------- .../private/kernel/arch/x86_64/arch_debug.h | 17 -- headers/private/kernel/arch/x86_64/arch_int.h | 78 ------- .../private/kernel/arch/x86_64/arch_kernel.h | 43 ---- .../kernel/arch/x86_64/arch_kernel_args.h | 14 -- .../kernel/arch/x86_64/arch_system_info.h | 28 --- .../private/kernel/arch/x86_64/arch_thread.h | 32 --- .../kernel/arch/x86_64/arch_thread_types.h | 32 --- .../kernel/arch/x86_64/arch_user_debugger.h | 6 - headers/private/kernel/arch/x86_64/arch_vm.h | 16 -- .../arch/x86_64/arch_vm_translation_map.h | 9 - .../kernel/arch/x86_64/arch_vm_types.h | 9 - .../private/kernel/arch/x86_64/descriptors.h | 180 --------------- src/system/boot/platform/bios_ia32/long_asm.S | 4 +- src/system/kernel/arch/x86_64/Jamfile | 36 --- .../kernel/arch/x86_64/arch_commpage.cpp | 21 -- src/system/kernel/arch/x86_64/arch_cpu.cpp | 199 ---------------- src/system/kernel/arch/x86_64/arch_debug.cpp | 102 -------- .../kernel/arch/x86_64/arch_debug_console.cpp | 218 ------------------ src/system/kernel/arch/x86_64/arch_elf.cpp | 173 -------------- .../kernel/arch/x86_64/arch_platform.cpp | 35 --- .../arch/x86_64/arch_real_time_clock.cpp | 45 ---- src/system/kernel/arch/x86_64/arch_smp.cpp | 37 --- .../kernel/arch/x86_64/arch_system_info.cpp | 21 -- src/system/kernel/arch/x86_64/arch_thread.cpp | 104 --------- src/system/kernel/arch/x86_64/arch_timer.cpp | 30 --- .../kernel/arch/x86_64/arch_user_debugger.cpp | 106 --------- src/system/kernel/arch/x86_64/arch_vm.cpp | 66 ------ .../arch/x86_64/arch_vm_translation_map.cpp | 52 ----- src/system/kernel/arch/x86_64/asm_offsets.cpp | 77 ------- 30 files changed, 3 insertions(+), 1889 deletions(-) delete mode 100644 headers/private/kernel/arch/x86_64/arch_cpu.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_debug.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_int.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_kernel.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_kernel_args.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_system_info.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_thread.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_thread_types.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_user_debugger.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_vm.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_vm_translation_map.h delete mode 100644 headers/private/kernel/arch/x86_64/arch_vm_types.h delete mode 100644 headers/private/kernel/arch/x86_64/descriptors.h delete mode 100644 src/system/kernel/arch/x86_64/Jamfile delete mode 100644 src/system/kernel/arch/x86_64/arch_commpage.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_cpu.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_debug.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_debug_console.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_elf.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_platform.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_real_time_clock.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_smp.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_system_info.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_thread.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_timer.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_user_debugger.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_vm.cpp delete mode 100644 src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp delete mode 100644 src/system/kernel/arch/x86_64/asm_offsets.cpp diff --git a/headers/private/kernel/arch/x86_64/arch_cpu.h b/headers/private/kernel/arch/x86_64/arch_cpu.h deleted file mode 100644 index 0eda6fae36..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_cpu.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_CPU_H -#define _KERNEL_ARCH_X86_64_CPU_H - - -#include "../common_x86/cpu.h" - -#ifndef _ASSEMBLER -# ifndef _BOOT_MODE -# include -# endif -#endif - - -// iframe types -#define IFRAME_TYPE_SYSCALL 0x1 -#define IFRAME_TYPE_OTHER 0x2 -#define IFRAME_TYPE_MASK 0xf - - -#ifndef _ASSEMBLER - - -struct tss { - uint32 _reserved1; - uint64 rsp0; - uint64 rsp1; - uint64 rsp2; - uint64 _reserved2; - uint64 ist1; - uint64 ist2; - uint64 ist3; - uint64 ist4; - uint64 ist5; - uint64 ist6; - uint64 ist7; - uint64 _reserved3; - uint16 _reserved4; - uint16 io_bitmap; -} _PACKED; - - -struct iframe { - unsigned long type; - unsigned long r15; - unsigned long r14; - unsigned long r13; - unsigned long r12; - unsigned long r11; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long rbp; - unsigned long rsi; - unsigned long rdi; - unsigned long rdx; - unsigned long rcx; - unsigned long rbx; - unsigned long rax; - unsigned long vector; - unsigned long error_code; - unsigned long rip; - unsigned long cs; - unsigned long flags; - - // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). - unsigned long user_rsp; - unsigned long user_ss; -} _PACKED; - -#define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) - - -typedef struct arch_cpu_info { - // CPU identification/feature information. - enum x86_vendors vendor; - uint32 feature[FEATURE_NUM]; - char model_name[49]; - const char* vendor_name; - int type; - int family; - int extended_family; - int stepping; - int model; - int extended_model; - - // TSS for this CPU. - struct tss tss; -} arch_cpu_info; - - -#ifndef _BOOT_MODE -extern segment_descriptor* gGDT; -#endif - - -#endif /* _ASSEMBLER */ - -#endif /* _KERNEL_ARCH_X86_64_CPU_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_debug.h b/headers/private/kernel/arch/x86_64/arch_debug.h deleted file mode 100644 index 6f06f95458..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_debug.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_DEBUG_H -#define _KERNEL_ARCH_X86_64_DEBUG_H - - -#include - - -struct arch_debug_registers { - uint64 rbp; -}; - - -#endif /* _KERNEL_ARCH_X86_64_DEBUG_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_int.h b/headers/private/kernel/arch/x86_64/arch_int.h deleted file mode 100644 index 9e8e987c78..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_int.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de. - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_INT_H -#define _KERNEL_ARCH_X86_64_INT_H - - -#define ARCH_INTERRUPT_BASE 0x20 -#define NUM_IO_VECTORS (256 - ARCH_INTERRUPT_BASE) - - -static inline void -arch_int_enable_interrupts_inline(void) -{ - asm volatile("sti"); -} - - -static inline int -arch_int_disable_interrupts_inline(void) -{ - unsigned long flags; - - asm volatile("pushf;\n" - "pop %0;\n" - "cli" : "=g" (flags)); - return (flags & 0x200) != 0; -} - - -static inline void -arch_int_restore_interrupts_inline(int oldState) -{ - if (oldState) - asm("sti"); -} - - -static inline bool -arch_int_are_interrupts_enabled_inline(void) -{ - unsigned long flags; - - asm volatile("pushf;\n" - "pop %0;\n" : "=g" (flags)); - return (flags & 0x200) != 0; -} - - -// map the functions to the inline versions -#define arch_int_enable_interrupts() arch_int_enable_interrupts_inline() -#define arch_int_disable_interrupts() arch_int_disable_interrupts_inline() -#define arch_int_restore_interrupts(status) \ - arch_int_restore_interrupts_inline(status) -#define arch_int_are_interrupts_enabled() \ - arch_int_are_interrupts_enabled_inline() - - -#ifdef __cplusplus - -typedef struct interrupt_controller_s { - const char *name; - void (*enable_io_interrupt)(int32 num); - void (*disable_io_interrupt)(int32 num); - void (*configure_io_interrupt)(int32 num, uint32 config); - bool (*is_spurious_interrupt)(int32 num); - bool (*is_level_triggered_interrupt)(int32 num); - bool (*end_of_interrupt)(int32 num); -} interrupt_controller; - - -void arch_int_set_interrupt_controller(const interrupt_controller &controller); - -#endif // __cplusplus - -#endif /* _KERNEL_ARCH_X86_64_INT_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel.h b/headers/private/kernel/arch/x86_64/arch_kernel.h deleted file mode 100644 index e19b5c25b8..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_kernel.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_KERNEL_H -#define _KERNEL_ARCH_X86_64_KERNEL_H - - -#ifndef _ASSEMBLER -# include -#endif - - -// Base of the kernel address space. -// When compiling the bootloader, KERNEL_BASE is set to the x86 base address, -// KERNEL_BASE_64BIT is set to where the kernel loaded to. -// For the kernel, KERNEL_BASE is the base of the kernel address space. This is -// NOT the address where the kernel is loaded to: the kernel is loaded in the -// top 2GB of the virtual address space as required by GCC's kernel code model. -// The whole kernel address space is the top 512GB of the address space. -#ifdef _BOOT_MODE -# define KERNEL_BASE 0x80000000 -# define KERNEL_BASE_64BIT 0xffffffff80000000ll -#else -# define KERNEL_BASE 0xffffff8000000000 -#endif - -#define KERNEL_SIZE 0x8000000000 -#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) - - -// Userspace address space layout. -#define USER_BASE 0x0 -#define USER_BASE_ANY 0x100000 -#define USER_SIZE 0x800000000000 -#define USER_TOP (USER_BASE + USER_SIZE) - -#define KERNEL_USER_DATA_BASE 0x7fffefff0000 -#define USER_STACK_REGION 0x7ffff0000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) - - -#endif /* _KERNEL_ARCH_X86_64_KERNEL_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_kernel_args.h b/headers/private/kernel/arch/x86_64/arch_kernel_args.h deleted file mode 100644 index 1ccfd8db41..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_kernel_args.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_KERNEL_ARGS_H -#define _KERNEL_ARCH_X86_64_KERNEL_ARGS_H - - -// x86_64 kernel is loaded loaded by the x86 bootloader, kernel_args is -// identical to x86. -#include "../x86/arch_kernel_args.h" - - -#endif /* _KERNEL_ARCH_X86_64_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_system_info.h b/headers/private/kernel/arch/x86_64/arch_system_info.h deleted file mode 100644 index 393f297d59..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_system_info.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_SYSTEM_INFO_H -#define _KERNEL_ARCH_X86_64_SYSTEM_INFO_H - - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _BOOT_MODE -status_t get_current_cpuid(cpuid_info *info, uint32 eax); -uint32 get_eflags(void); -void set_eflags(uint32 value); -#endif - -//status_t _user_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); - -#ifdef __cplusplus -} -#endif - -#endif /* _KRENEL_ARCH_X86_64_SYSTEM_INFO_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread.h b/headers/private/kernel/arch/x86_64/arch_thread.h deleted file mode 100644 index 80f200a8c5..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_thread.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_THREAD_H -#define _KERNEL_ARCH_X86_64_THREAD_H - - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -static inline Thread * -arch_thread_get_current_thread(void) -{ - return NULL; -} - -static inline void -arch_thread_set_current_thread(Thread *t) -{ - -} - -#ifdef __cplusplus -} -#endif - -#endif /* _KERNEL_ARCH_X86_64_THREAD_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_thread_types.h b/headers/private/kernel/arch/x86_64/arch_thread_types.h deleted file mode 100644 index 299371691a..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_thread_types.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_THREAD_TYPES_H -#define _KERNEL_ARCH_X86_64_THREAD_TYPES_H - - -#include - - -// x86_64-specific thread information. -struct arch_thread { - // Stack pointer. - addr_t rsp; - - // FPU saved state - this must be 16 byte aligned. - uint8 fpu_state[512] __attribute__((aligned(16))); -} __attribute__((aligned(16))); - -struct arch_team { - // gcc treats empty structures as zero-length in C, but as if they contain - // a char in C++. So we have to put a dummy in to be able to use the struct - // from both in a consistent way. - char dummy; -}; - -struct arch_fork_arg { - struct iframe iframe; -}; - -#endif /* _KERNEL_ARCH_X86_64_THREAD_TYPES_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_user_debugger.h b/headers/private/kernel/arch/x86_64/arch_user_debugger.h deleted file mode 100644 index 9053ec5e62..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_user_debugger.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _KERNEL_ARCH_X86_64_USER_DEBUGGER_H -#define _KERNEL_ARCH_X86_64_USER_DEBUGGER_H - -#include "../x86/arch_user_debugger.h" - -#endif /* _KERNEL_ARCH_X86_64_USER_DEBUGGER_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm.h b/headers/private/kernel/arch/x86_64/arch_vm.h deleted file mode 100644 index 033d97d78b..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_vm.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_VM_H -#define _KERNEL_ARCH_X86_64_VM_H - -/* This many pages will be read/written on I/O if possible */ - -#define NUM_IO_PAGES 4 - /* 16 kB */ - -#define PAGE_SHIFT 12 - -#endif /* _KERNEL_ARCH_X86_64_VM_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h b/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h deleted file mode 100644 index 98575cbe4c..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_vm_translation_map.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H -#define _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H - - -#endif /* _KERNEL_ARCH_X86_64_VM_TRANSLATION_MAP_H */ diff --git a/headers/private/kernel/arch/x86_64/arch_vm_types.h b/headers/private/kernel/arch/x86_64/arch_vm_types.h deleted file mode 100644 index ab090369bc..0000000000 --- a/headers/private/kernel/arch/x86_64/arch_vm_types.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_VM_TYPES_H -#define _KERNEL_ARCH_X86_64_VM_TYPES_H - - -#endif /* _KERNEL_ARCH_X86_64_VM_TYPES_H */ diff --git a/headers/private/kernel/arch/x86_64/descriptors.h b/headers/private/kernel/arch/x86_64/descriptors.h deleted file mode 100644 index 445682ca1c..0000000000 --- a/headers/private/kernel/arch/x86_64/descriptors.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ -#ifndef _KERNEL_ARCH_X86_64_DESCRIPTORS_H -#define _KERNEL_ARCH_X86_64_DESCRIPTORS_H - - -// Segment definitions. -// Note that the ordering of these is important to SYSCALL/SYSRET. -#define KERNEL_CODE_SEG 0x08 -#define KERNEL_DATA_SEG 0x10 -#define USER_DATA_SEG 0x1b -#define USER_CODE_SEG 0x23 - - -#ifndef _ASSEMBLER - - -#define TSS_BASE_SEGMENT 5 -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) - - -// Structure of a segment descriptor. -struct segment_descriptor { - uint32 limit0 : 16; - uint32 base0 : 24; - uint32 type : 4; - uint32 desc_type : 1; - uint32 dpl : 2; - uint32 present : 1; - uint32 limit1 : 4; - uint32 available : 1; - uint32 long_mode : 1; - uint32 d_b : 1; - uint32 granularity : 1; - uint32 base1 : 8; -} _PACKED; - -// Structure of a TSS segment descriptor. -struct tss_descriptor { - uint32 limit0 : 16; - uint32 base0 : 24; - uint32 type : 4; - uint32 desc_type : 1; - uint32 dpl : 2; - uint32 present : 1; - uint32 limit1 : 4; - uint32 available : 1; - uint32 unused1 : 2; - uint32 granularity : 1; - uint32 base1 : 8; - uint32 base2 : 32; - uint32 unused2 : 32; -} _PACKED; - -// Structure of an interrupt descriptor. -struct interrupt_descriptor { - uint32 base0 : 16; - uint32 sel : 16; - uint32 ist : 3; - uint32 unused1 : 5; - uint32 type : 4; - uint32 unused2 : 1; - uint32 dpl : 2; - uint32 present : 1; - uint32 base1 : 16; - uint32 base2 : 32; - uint32 reserved : 32; -} _PACKED; - -struct gdt_idt_descr { - uint16 limit; - addr_t base; -} _PACKED; - -enum descriptor_privilege_levels { - DPL_KERNEL = 0, - DPL_USER = 3, -}; - -enum descriptor_types { - // Code/data descriptor types. - DT_CODE_EXECUTE_ONLY = 0x8, - DT_CODE_ACCESSED = 0x9, - DT_CODE_READABLE = 0xa, - DT_CODE_CONFORM = 0xc, - DT_DATA_READ_ONLY = 0x0, - DT_DATA_ACCESSED = 0x1, - DT_DATA_WRITEABLE = 0x2, - DT_DATA_EXPANSION_DOWN = 0x4, - - // System descriptor types. - DT_TSS = 9, - - // Descriptor types - DT_SYSTEM_SEGMENT = 0, - DT_CODE_DATA_SEGMENT = 1, -}; - -enum gate_types { - GATE_INTERRUPT = 14, - GATE_TRAP = 15, -}; - - -static inline void -clear_segment_descriptor(segment_descriptor* desc) -{ - *(uint64*)desc = 0; -} - - -static inline void -set_segment_descriptor(segment_descriptor* desc, uint8 type, uint8 dpl) -{ - clear_segment_descriptor(desc); - - // In 64-bit mode the CPU ignores the base/limit of code/data segments, - // it always treats base as 0 and does no limit checks. - desc->base0 = 0; - desc->base1 = 0; - desc->limit0 = 0xffff; - desc->limit1 = 0xf; - desc->granularity = 1; - - desc->type = type; - desc->desc_type = DT_CODE_DATA_SEGMENT; - desc->dpl = dpl; - desc->present = 1; - - desc->long_mode = (type & DT_CODE_EXECUTE_ONLY) ? 1 : 0; - // Must be set to 1 for code segments only. -} - - -static inline void -set_tss_descriptor(segment_descriptor* _desc, uint64 base, uint32 limit) -{ - clear_segment_descriptor(_desc); - clear_segment_descriptor(&_desc[1]); - - // The TSS descriptor is a special format in 64-bit mode, it is 16 bytes - // instead of 8. - tss_descriptor* desc = (tss_descriptor*)_desc; - - desc->base0 = base & 0xffffff; - desc->base1 = (base >> 24) & 0xff; - desc->base2 = (base >> 32); - desc->limit0 = limit & 0xffff; - desc->limit1 = (limit >> 16) & 0xf; - - desc->present = 1; - desc->type = DT_TSS; - desc->desc_type = DT_SYSTEM_SEGMENT; - desc->dpl = DPL_KERNEL; -} - - -static inline void -set_interrupt_descriptor(interrupt_descriptor* desc, uint64 addr, uint32 type, - uint16 seg, uint32 dpl, uint32 ist) -{ - desc->base0 = addr & 0xffff; - desc->base1 = (addr >> 16) & 0xffff; - desc->base2 = (addr >> 32) & 0xffffffff; - desc->sel = seg; - desc->ist = ist; - desc->type = type; - desc->dpl = dpl; - desc->present = 1; - desc->unused1 = 0; - desc->unused2 = 0; - desc->reserved = 0; -} - - -#endif /* _ASSEMBLER */ - -#endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */ diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 3a52720077..c14889a8f6 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -6,7 +6,9 @@ #include -#include +#define __x86_64__ +#include +#undef __x86_64__ .code32 diff --git a/src/system/kernel/arch/x86_64/Jamfile b/src/system/kernel/arch/x86_64/Jamfile deleted file mode 100644 index 3f32a22ad3..0000000000 --- a/src/system/kernel/arch/x86_64/Jamfile +++ /dev/null @@ -1,36 +0,0 @@ -SubDir HAIKU_TOP src system kernel arch x86_64 ; - -SubDirHdrs [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) system kernel ] ; - # for syscall_numbers.h - -UsePrivateKernelHeaders ; -UsePrivateHeaders shared ; - -KernelMergeObject kernel_arch_x86_64.o : - arch_commpage.cpp - arch_cpu.cpp - arch_debug.cpp - arch_debug_console.cpp - arch_elf.cpp - arch_int.cpp - arch_interrupts.S - arch_platform.cpp - arch_real_time_clock.cpp - arch_smp.cpp - arch_system_info.cpp - arch_thread.cpp - arch_timer.cpp - arch_user_debugger.cpp - arch_vm.cpp - arch_vm_translation_map.cpp - : - $(TARGET_KERNEL_PIC_CCFLAGS) -; - -CreateAsmStructOffsetsHeader asm_offsets.h : asm_offsets.cpp ; - -# We need to specify the dependency on the generated syscalls file explicitly. -#Includes [ FGristFiles arch_x86.S arch_interrupts.S ] -# : syscall_numbers.h ; -#Includes [ FGristFiles arch_interrupts.S ] -# : syscall_table.h ; diff --git a/src/system/kernel/arch/x86_64/arch_commpage.cpp b/src/system/kernel/arch/x86_64/arch_commpage.cpp deleted file mode 100644 index 5dcb59870f..0000000000 --- a/src/system/kernel/arch/x86_64/arch_commpage.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - - -status_t -arch_commpage_init(void) -{ - return B_OK; -} - - -status_t -arch_commpage_init_post_cpus(void) -{ - return B_OK; -} diff --git a/src/system/kernel/arch/x86_64/arch_cpu.cpp b/src/system/kernel/arch/x86_64/arch_cpu.cpp deleted file mode 100644 index 2141b86aa6..0000000000 --- a/src/system/kernel/arch/x86_64/arch_cpu.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - * - * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ - - -#include - -#include - - -status_t -arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) -{ - return B_OK; -} - - -status_t -arch_cpu_init_percpu(kernel_args* args, int cpu) -{ - return B_OK; -} - - -status_t -arch_cpu_init(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_cpu_init_post_vm(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_cpu_init_post_modules(kernel_args* args) -{ - return B_OK; -} - - -void -arch_cpu_user_TLB_invalidate(void) -{ - -} - - -void -arch_cpu_global_TLB_invalidate(void) -{ - -} - - -void -arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) -{ - -} - - -void -arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) -{ - -} - - -ssize_t -arch_cpu_user_strlcpy(char* to, const char* from, size_t size, - addr_t* faultHandler) -{ - int fromLength = 0; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (to == NULL && size > 0) - goto error; - - *faultHandler = (addr_t)&&error; - - if (size > 0) { - to[--size] = '\0'; - // copy - for ( ; size; size--, fromLength++, to++, from++) { - if ((*to = *from) == '\0') - break; - } - } - - // count any leftover from chars - while (*from++ != '\0') { - fromLength++; - } - - *faultHandler = oldFaultHandler; - return fromLength; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memcpy(void* to, const void* from, size_t size, - addr_t* faultHandler) -{ - char* d = (char*)to; - const char* s = (const char*)from; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (s == NULL) - goto error; - - *faultHandler = (addr_t)&&error; - - for (; size != 0; size--) { - *d++ = *s++; - } - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) -{ - char* xs = (char*)s; - addr_t oldFaultHandler = *faultHandler; - - // this check is to trick the gcc4 compiler and have it keep the error label - if (s == NULL) - goto error; - - *faultHandler = (addr_t)&&error; - - while (count--) - *xs++ = c; - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler; - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_shutdown(bool rebootSystem) -{ - return B_ERROR; -} - - -void -arch_cpu_idle(void) -{ - asm("hlt"); -} - - -void -arch_cpu_sync_icache(void* address, size_t length) -{ - // Instruction cache is always consistent on x86. -} - - -void -arch_cpu_memory_read_barrier(void) -{ - asm volatile("lfence" : : : "memory"); -} - - -void -arch_cpu_memory_write_barrier(void) -{ - asm volatile("sfence" : : : "memory"); -} - diff --git a/src/system/kernel/arch/x86_64/arch_debug.cpp b/src/system/kernel/arch/x86_64/arch_debug.cpp deleted file mode 100644 index b9946bb186..0000000000 --- a/src/system/kernel/arch/x86_64/arch_debug.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -void -arch_debug_save_registers(struct arch_debug_registers* registers) -{ - -} - - -void -arch_debug_stack_trace(void) -{ - -} - - -bool -arch_debug_contains_call(Thread *thread, const char *symbol, - addr_t start, addr_t end) -{ - return false; -} - - -void * -arch_debug_get_caller(void) -{ - return NULL; -} - - -int32 -arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, - int32 skipIframes, int32 skipFrames, uint32 flags) -{ - return 0; -} - - -void* -arch_debug_get_interrupt_pc(bool* _isSyscall) -{ - return NULL; -} - - -void -arch_debug_unset_current_thread(void) -{ - -} - - -bool -arch_is_debug_variable_defined(const char* variableName) -{ - return false; -} - - -status_t -arch_set_debug_variable(const char* variableName, uint64 value) -{ - return B_OK; -} - - -status_t -arch_get_debug_variable(const char* variableName, uint64* value) -{ - return B_OK; -} - - -ssize_t -arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) -{ - return B_ERROR; -} - - -status_t -arch_debug_init(kernel_args *args) -{ - return B_OK; -} - -void -arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, - void (*function)(void*), void* parameter) -{ - // To be implemented in asm, not here. -} diff --git a/src/system/kernel/arch/x86_64/arch_debug_console.cpp b/src/system/kernel/arch/x86_64/arch_debug_console.cpp deleted file mode 100644 index 8e5db41e05..0000000000 --- a/src/system/kernel/arch/x86_64/arch_debug_console.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de - * Copyright 2001, Rob Judd - * Copyright 2002, Marcus Overhagen - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - * - * Copyright 2001, Travis Geiselbrecht. All rights reserved. - * Distributed under the terms of the NewOS License. - */ - - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - - -enum serial_register_offsets { - SERIAL_TRANSMIT_BUFFER = 0, - SERIAL_RECEIVE_BUFFER = 0, - SERIAL_DIVISOR_LATCH_LOW = 0, - SERIAL_DIVISOR_LATCH_HIGH = 1, - SERIAL_FIFO_CONTROL = 2, - SERIAL_LINE_CONTROL = 3, - SERIAL_MODEM_CONTROL = 4, - SERIAL_LINE_STATUS = 5, - SERIAL_MODEM_STATUS = 6, -}; - - -static const uint32 kSerialBaudRate = 115200; -static uint16 sSerialBasePort = 0x3f8; - // COM1 is the default debug output port - -static spinlock sSerialOutputSpinlock = B_SPINLOCK_INITIALIZER; - - -static void -init_serial_port(uint16 basePort, uint32 baudRate) -{ - sSerialBasePort = basePort; - - uint16 divisor = (uint16)(115200 / baudRate); - - out8(0x80, sSerialBasePort + SERIAL_LINE_CONTROL); /* set divisor latch access bit */ - out8(divisor & 0xf, sSerialBasePort + SERIAL_DIVISOR_LATCH_LOW); - out8(divisor >> 8, sSerialBasePort + SERIAL_DIVISOR_LATCH_HIGH); - out8(3, sSerialBasePort + SERIAL_LINE_CONTROL); /* 8N1 */ -} - - -static void -put_char(const char c) -{ - // wait until the transmitter empty bit is set - while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0) - asm volatile ("pause;"); - - out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER); -} - - -// #pragma mark - - - -void -arch_debug_remove_interrupt_handler(uint32 line) -{ - -} - - -void -arch_debug_install_interrupt_handlers(void) -{ - -} - - -int -arch_debug_blue_screen_try_getchar(void) -{ - return -1; -} - - -char -arch_debug_blue_screen_getchar(void) -{ - while(true) - PAUSE(); - return 0; -} - - -int -arch_debug_serial_try_getchar(void) -{ - uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS); - if (lineStatus == 0xff) { - // The "data available" bit is set, but also all error bits. Likely we - // don't have a valid I/O port. - return -1; - } - - if ((lineStatus & 0x1) == 0) - return -1; - - return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER); -} - - -char -arch_debug_serial_getchar(void) -{ - while (true) { - uint8 lineStatus = in8(sSerialBasePort + SERIAL_LINE_STATUS); - if (lineStatus == 0xff) { - // The "data available" bit is set, but also all error bits. Likely - // we don't have a valid I/O port. - return 0; - } - - if ((lineStatus & 0x1) != 0) - break; - - PAUSE(); - } - - return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER); -} - - -static void -_arch_debug_serial_putchar(const char c) -{ - if (c == '\n') { - put_char('\r'); - put_char('\n'); - } else if (c != '\r') - put_char(c); -} - -void -arch_debug_serial_putchar(const char c) -{ - cpu_status state = 0; - if (!debug_debugger_running()) { - state = disable_interrupts(); - acquire_spinlock(&sSerialOutputSpinlock); - } - - _arch_debug_serial_putchar(c); - - if (!debug_debugger_running()) { - release_spinlock(&sSerialOutputSpinlock); - restore_interrupts(state); - } -} - - -void -arch_debug_serial_puts(const char *s) -{ - cpu_status state = 0; - if (!debug_debugger_running()) { - state = disable_interrupts(); - acquire_spinlock(&sSerialOutputSpinlock); - } - - while (*s != '\0') { - _arch_debug_serial_putchar(*s); - s++; - } - - if (!debug_debugger_running()) { - release_spinlock(&sSerialOutputSpinlock); - restore_interrupts(state); - } -} - - -void -arch_debug_serial_early_boot_message(const char *string) -{ - // this function will only be called in fatal situations - // ToDo: also enable output via text console?! - arch_debug_console_init(NULL); - arch_debug_serial_puts(string); -} - - -status_t -arch_debug_console_init(kernel_args *args) -{ - // only use the port if we could find one, else use the standard port - if (args != NULL && args->platform_args.serial_base_ports[0] != 0) - sSerialBasePort = args->platform_args.serial_base_ports[0]; - - init_serial_port(sSerialBasePort, kSerialBaudRate); - - return B_OK; -} - - -status_t -arch_debug_console_init_settings(kernel_args *args) -{ - return B_OK; -} diff --git a/src/system/kernel/arch/x86_64/arch_elf.cpp b/src/system/kernel/arch/x86_64/arch_elf.cpp deleted file mode 100644 index 30f022d7db..0000000000 --- a/src/system/kernel/arch/x86_64/arch_elf.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - -#ifdef _BOOT_MODE -# include -#endif - -#include - -#include -#include - -#include - - -#ifndef _BOOT_MODE -// Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. - -status_t -elf_load_user_image(const char *path, Team *team, int flags, addr_t *_entry) -{ - return B_ERROR; -} - -image_id -load_kernel_add_on(const char *path) -{ - return 0; -} - -status_t -unload_kernel_add_on(image_id id) -{ - return B_ERROR; -} - -status_t -elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, - const char **_symbolName, const char **_imageName, bool *_exactMatch) -{ - return B_ERROR; -} - -addr_t -elf_debug_lookup_symbol(const char* searchName) -{ - return 0; -} - -struct elf_image_info * -elf_get_kernel_image() -{ - return NULL; -} - -image_id -elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, - addr_t data, size_t dataSize) -{ - return B_ERROR; -} - -status_t -elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, - size_t size, int32 type) -{ - return B_ERROR; -} - -status_t -elf_init(struct kernel_args *args) -{ - return B_OK; -} - -status_t -get_image_symbol(image_id image, const char *name, int32 symbolType, - void **_symbolLocation) -{ - return B_OK; -} - -status_t -_user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, - int32* _symbolCount, char* stringTable, size_t* _stringTableSize, - addr_t* _imageDelta) -{ - return B_ERROR; -} -#endif - -#ifdef _BOOT_MODE -status_t -boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, - int relLength) -//#else -//int -//arch_elf_relocate_rel(struct elf_image_info *image, -// struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) -//#endif -{ - dprintf("arch_elf_relocate_rel: not supported on x86_64\n"); - return B_ERROR; -} - - -//#ifdef _BOOT_MODE -status_t -boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, - int relLength) -//#else -//int -//arch_elf_relocate_rela(struct elf_image_info *image, -// struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) -//#endif -{ - for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { - int type = ELF64_R_TYPE(rel[i].r_info); - int symIndex = ELF64_R_SYM(rel[i].r_info); - Elf64_Addr symAddr = 0; - - // Resolve the symbol, if any. - if (symIndex != 0) { - Elf64_Sym* symbol = SYMBOL(image, symIndex); - - status_t status; -//#ifdef _BOOT_MODE - status = boot_elf_resolve_symbol(image, symbol, &symAddr); -//#else -// status = elf_resolve_symbol(image, symbol, resolveImage, &S); -//#endif - if (status < B_OK) - return status; - } - - // Address of the relocation. - Elf64_Addr relocAddr = image->text_region.delta + rel[i].r_offset; - - // Calculate the relocation value. - Elf64_Addr relocValue; - switch(type) { - case R_X86_64_NONE: - continue; - case R_X86_64_64: - relocValue = symAddr + rel[i].r_addend; - break; - case R_X86_64_PC32: - relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; - break; - case R_X86_64_GLOB_DAT: - case R_X86_64_JUMP_SLOT: - relocValue = symAddr + rel[i].r_addend; - break; - case R_X86_64_RELATIVE: - relocValue = image->text_region.delta + rel[i].r_addend; - break; - default: - dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", - type); - return B_BAD_DATA; - } -#ifdef _BOOT_MODE - boot_elf64_set_relocation(relocAddr, relocValue); -#else - *(Elf64_Addr *)relocAddr = relocValue; -#endif - } - - return B_OK; -} -#endif diff --git a/src/system/kernel/arch/x86_64/arch_platform.cpp b/src/system/kernel/arch/x86_64/arch_platform.cpp deleted file mode 100644 index c556b5639d..0000000000 --- a/src/system/kernel/arch/x86_64/arch_platform.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2006, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Ingo Weinhold - * Axel Dörfler, axeld@pinc-software.de - */ - - -#include -//#include - - -status_t -arch_platform_init(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_platform_init_post_vm(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_platform_init_post_thread(struct kernel_args *args) -{ - //apm_init(args); - return B_OK; -} - diff --git a/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp b/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp deleted file mode 100644 index 1ada20b9ea..0000000000 --- a/src/system/kernel/arch/x86_64/arch_real_time_clock.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include -#include - - -status_t -arch_rtc_init(struct kernel_args *args, struct real_time_data *data) -{ - return B_OK; -} - - -uint32 -arch_rtc_get_hw_time(void) -{ - return 0; -} - - -void -arch_rtc_set_hw_time(uint32 seconds) -{ - -} - - -void -arch_rtc_set_system_time_offset(struct real_time_data *data, bigtime_t offset) -{ - -} - - -bigtime_t -arch_rtc_get_system_time_offset(struct real_time_data *data) -{ - return 0; -} diff --git a/src/system/kernel/arch/x86_64/arch_smp.cpp b/src/system/kernel/arch/x86_64/arch_smp.cpp deleted file mode 100644 index c8a6657378..0000000000 --- a/src/system/kernel/arch/x86_64/arch_smp.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -status_t -arch_smp_init(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_smp_per_cpu_init(kernel_args *args, int32 cpu) -{ - return B_OK; -} - - -void -arch_smp_send_broadcast_ici(void) -{ - -} - - -void -arch_smp_send_ici(int32 target_cpu) -{ - -} diff --git a/src/system/kernel/arch/x86_64/arch_system_info.cpp b/src/system/kernel/arch/x86_64/arch_system_info.cpp deleted file mode 100644 index b9f1d7b31e..0000000000 --- a/src/system/kernel/arch/x86_64/arch_system_info.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - - -status_t -arch_get_system_info(system_info *info, size_t size) -{ - return B_OK; -} - - -status_t -arch_system_info_init(struct kernel_args *args) -{ - return B_OK; -} diff --git a/src/system/kernel/arch/x86_64/arch_thread.cpp b/src/system/kernel/arch/x86_64/arch_thread.cpp deleted file mode 100644 index d09c11ab9d..0000000000 --- a/src/system/kernel/arch/x86_64/arch_thread.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include -#include - - -status_t -arch_thread_init(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_team_init_team_struct(Team *p, bool kernel) -{ - return B_ERROR; -} - - -status_t -arch_thread_init_thread_struct(Thread *thread) -{ - return B_ERROR; -} - - -void -arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, - void (*function)(void*), const void* data) -{ - -} - - -status_t -arch_thread_init_tls(Thread *thread) -{ - return B_ERROR; -} - - -void -arch_thread_context_switch(Thread *from, Thread *to) -{ - -} - - -void -arch_thread_dump_info(void *info) -{ - -} - - -status_t -arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, - void* args2) -{ - return B_ERROR; -} - - -bool -arch_on_signal_stack(Thread *thread) -{ - return false; -} - - -status_t -arch_setup_signal_frame(Thread* thread, struct sigaction* action, - struct signal_frame_data* signalFrameData) -{ - return B_ERROR; -} - - -int64 -arch_restore_signal_frame(struct signal_frame_data* signalFrameData) -{ - return 0; -} - - -void -arch_store_fork_frame(struct arch_fork_arg *arg) -{ - -} - - -void -arch_restore_fork_frame(struct arch_fork_arg* arg) -{ - -} diff --git a/src/system/kernel/arch/x86_64/arch_timer.cpp b/src/system/kernel/arch/x86_64/arch_timer.cpp deleted file mode 100644 index c320b6bf98..0000000000 --- a/src/system/kernel/arch/x86_64/arch_timer.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -void -arch_timer_set_hardware_timer(bigtime_t timeout) -{ - -} - - -void -arch_timer_clear_hardware_timer(void) -{ - -} - - -int -arch_init_timer(kernel_args *args) -{ - return 0; -} diff --git a/src/system/kernel/arch/x86_64/arch_user_debugger.cpp b/src/system/kernel/arch/x86_64/arch_user_debugger.cpp deleted file mode 100644 index a9931c674d..0000000000 --- a/src/system/kernel/arch/x86_64/arch_user_debugger.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -// The software breakpoint instruction (int3). -const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; - - -void -arch_clear_team_debug_info(struct arch_team_debug_info *info) -{ - -} - - -void -arch_destroy_team_debug_info(struct arch_team_debug_info *info) -{ - -} - - -void -arch_clear_thread_debug_info(struct arch_thread_debug_info *info) -{ - -} - - -void -arch_destroy_thread_debug_info(struct arch_thread_debug_info *info) -{ - -} - - -void -arch_update_thread_single_step() -{ - -} - - -void -arch_set_debug_cpu_state(const debug_cpu_state *cpuState) -{ - -} - - -void -arch_get_debug_cpu_state(debug_cpu_state *cpuState) -{ - -} - - -status_t -arch_set_breakpoint(void *address) -{ - return B_OK; -} - - -status_t -arch_clear_breakpoint(void *address) -{ - return B_OK; -} - - -status_t -arch_set_watchpoint(void *address, uint32 type, int32 length) -{ - return B_OK; -} - - -status_t -arch_clear_watchpoint(void *address) -{ - return B_OK; -} - - -bool -arch_has_breakpoints(struct arch_team_debug_info *info) -{ - return false; -} - - -void -x86_init_user_debug() -{ - -} - diff --git a/src/system/kernel/arch/x86_64/arch_vm.cpp b/src/system/kernel/arch/x86_64/arch_vm.cpp deleted file mode 100644 index db842ad6d3..0000000000 --- a/src/system/kernel/arch/x86_64/arch_vm.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - -#include - - -status_t -arch_vm_init(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_post_area(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_end(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_post_modules(kernel_args *args) -{ - return B_OK; -} - - -void -arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to) -{ - -} - - -bool -arch_vm_supports_protection(uint32 protection) -{ - return true; -} - - -void -arch_vm_unset_memory_type(struct VMArea *area) -{ - -} - - -status_t -arch_vm_set_memory_type(struct VMArea *area, phys_addr_t physicalBase, - uint32 type) -{ - return B_OK; -} diff --git a/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp deleted file mode 100644 index be0f2d1a40..0000000000 --- a/src/system/kernel/arch/x86_64/arch_vm_translation_map.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. - */ - - -#include - - -status_t -arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map) -{ - return B_ERROR; -} - - -status_t -arch_vm_translation_map_init(kernel_args *args, - VMPhysicalPageMapper** _physicalPageMapper) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_init_post_sem(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_init_post_area(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_early_map(kernel_args *args, addr_t va, phys_addr_t pa, - uint8 attributes, phys_addr_t (*get_free_page)(kernel_args *)) -{ - return B_ERROR; -} - - -bool -arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, - uint32 protection) -{ - return true; -} diff --git a/src/system/kernel/arch/x86_64/asm_offsets.cpp b/src/system/kernel/arch/x86_64/asm_offsets.cpp deleted file mode 100644 index b09f817534..0000000000 --- a/src/system/kernel/arch/x86_64/asm_offsets.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2007-2011, Ingo Weinhold, ingo_weinhold@gmx.de. - * Distributed under the terms of the MIT License. - */ - -// This file is used to get C structure offsets into assembly code. -// The build system assembles the file and processes the output to create -// a header file with macro definitions, that can be included from assembly -// code. - - -#include - -#include -//#include -//#include -//#include -//#include - - -#define DEFINE_MACRO(macro, value) DEFINE_COMPUTED_ASM_MACRO(macro, value) - -#define DEFINE_OFFSET_MACRO(prefix, structure, member) \ - DEFINE_MACRO(prefix##_##member, offsetof(struct structure, member)); - -#define DEFINE_SIZEOF_MACRO(prefix, structure) \ - DEFINE_MACRO(prefix##_sizeof, sizeof(struct structure)); - - -void -dummy() -{ - // struct cpu_ent - //DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler); - //DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer); - - // struct Thread - //DEFINE_OFFSET_MACRO(THREAD, Thread, time_lock); - //DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_time); - //DEFINE_OFFSET_MACRO(THREAD, Thread, user_time); - //DEFINE_OFFSET_MACRO(THREAD, Thread, last_time); - //DEFINE_OFFSET_MACRO(THREAD, Thread, in_kernel); - //DEFINE_OFFSET_MACRO(THREAD, Thread, flags); - //DEFINE_OFFSET_MACRO(THREAD, Thread, kernel_stack_top); - //DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); - - // struct iframe - DEFINE_SIZEOF_MACRO(IFRAME, iframe); - DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); - - // struct syscall_info - //DEFINE_SIZEOF_MACRO(SYSCALL_INFO, syscall_info); - //DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, function); - //DEFINE_OFFSET_MACRO(SYSCALL_INFO, syscall_info, parameter_size); - - // struct x86_optimized_functions - //DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, - // memcpy); - //DEFINE_OFFSET_MACRO(X86_OPTIMIZED_FUNCTIONS, x86_optimized_functions, - // memset); - - // struct signal_frame_data - //DEFINE_SIZEOF_MACRO(SIGNAL_FRAME_DATA, signal_frame_data); - //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, info); - //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context); - //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data); - //DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler); - - // struct ucontext_t - //DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext); - - // struct vregs - //DEFINE_SIZEOF_MACRO(VREGS, vregs); - - // struct siginfo_t - //DEFINE_OFFSET_MACRO(SIGINFO_T, __siginfo_t, si_signo); -} From cbfe5fcd171cee34562e5f86ef9586c027a1dd30 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 3 Jul 2012 17:38:18 +0100 Subject: [PATCH 059/273] Removed redundant x86 sources/headers. --- headers/private/kernel/arch/x86/selector.h | 32 -------- headers/private/kernel/arch/x86/types.h | 31 ------- src/system/kernel/arch/x86/Jamfile | 1 - src/system/kernel/arch/x86/arch_cpu.cpp | 5 -- src/system/kernel/arch/x86/arch_selector.cpp | 86 -------------------- 5 files changed, 155 deletions(-) delete mode 100644 headers/private/kernel/arch/x86/selector.h delete mode 100644 headers/private/kernel/arch/x86/types.h delete mode 100644 src/system/kernel/arch/x86/arch_selector.cpp diff --git a/headers/private/kernel/arch/x86/selector.h b/headers/private/kernel/arch/x86/selector.h deleted file mode 100644 index 8dee724517..0000000000 --- a/headers/private/kernel/arch/x86/selector.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** Copyright 2002, Michael Noisternig. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef _KERNEL_ARCH_x86_SELECTOR_H -#define _KERNEL_ARCH_x86_SELECTOR_H - -typedef uint32 selector_id; -typedef uint64 selector_type; - -// DATA segments are read-only -// CODE segments are execute-only -// both can be modified by using the suffixed enum versions -// legend: w = writable -// d = expand down -// r = readable -// c = conforming -enum segment_type { - DATA = 0x8, DATA_w, DATA_d, DATA_wd, CODE, CODE_r, CODE_c, CODE_rc -}; - -#define SELECTOR(base,limit,type,mode32) \ - (((uint64)(((((uint32)base)>>16)&0xff) | (((uint32)base)&0xff000000) | ((type)<<9) | ((mode32)<<22) | (1<<15))<<32) \ - | ( (limit) >= (1<<20) ? (((limit)>>12)&0xffff) | ((uint64)(((limit)>>12)&0xf0000)<<32) | ((uint64)1<<(23+32)) : ((limit)&0xffff) | ((uint64)((limit)&0xf0000)<<32) ) \ - | ((((uint32)base)&0xffff)<<16)) - -void i386_selector_init( void *gdt ); -selector_id i386_selector_add( selector_type selector ); -void i386_selector_remove( selector_id id ); -selector_type i386_selector_get( selector_id id ); - -#endif diff --git a/headers/private/kernel/arch/x86/types.h b/headers/private/kernel/arch/x86/types.h deleted file mode 100644 index c70a4ecf3c..0000000000 --- a/headers/private/kernel/arch/x86/types.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -** Copyright 2001, Travis Geiselbrecht. All rights reserved. -** Distributed under the terms of the NewOS License. -*/ -#ifndef _ARCH_x86_TYPES_H -#define _ARCH_x86_TYPES_H - -#ifndef WIN32 - typedef unsigned long long uint64; - typedef long long int64; -#else /* WIN32 */ - typedef unsigned __int64 uint64; - typedef __int64 int64; -#endif - -typedef unsigned long uint32; -typedef long int32; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned char uint8; -typedef char int8; -typedef unsigned long addr; - -#define _OBOS_TIME_T_ int /* basic time_t type */ - -/* define this as not all platforms have it set, but we'll make sure as - * some conditional checks need it - */ -#define __INTEL__ 1 - -#endif /* _ARCH_x86_TYPES_H */ diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index b0d08957c8..c2b29afaaa 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -36,7 +36,6 @@ if $(TARGET_ARCH) = x86_64 { arch_debug.cpp arch_elf.cpp arch_platform.cpp -# arch_selector.cpp arch_real_time_clock.cpp arch_smp.cpp arch_thread.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 9ce5d7b867..6d5a322218 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include "interrupts.h" @@ -822,10 +821,6 @@ arch_cpu_init_post_vm(kernel_args *args) create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - // currently taken out of the build, because it's not yet used (and assumes - // (a fixed number of used GDT entries) - //i386_selector_init(gGDT); // pass the new gdt - // allocate an area for the double fault stacks virtual_address_restrictions virtualRestrictions = {}; virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; diff --git a/src/system/kernel/arch/x86/arch_selector.cpp b/src/system/kernel/arch/x86/arch_selector.cpp deleted file mode 100644 index c9ade36f06..0000000000 --- a/src/system/kernel/arch/x86/arch_selector.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -** Copyright 2002, Michael Noisternig. All rights reserved. -** Distributed under the terms of the NewOS License. -** Distributed under the terms of the MIT License as part of the OpenBeOS project. -*/ -#include -#include -#include -#include - -#include - -#define MAX_SELECTORS (GDT_LIMIT/8) -#define ENTRIES (MAX_SELECTORS/(sizeof(uint32)*8)) - -static uint32 selector_bitmap[ENTRIES] - = { 0x000000ff }; // first 8 selectors reserved - -static selector_type *gdt_table; -static struct gdt_idt_descr descr = { GDT_LIMIT - 1, NULL }; - -void i386_selector_init( void *gdt ) -{ - gdt_table = (selector_type *)gdt; - descr.b = (unsigned int *)gdt_table; -} - -// creates a new selector in the gdt of given type (use SELECTOR macro) -// IN: selector type -// RET: selector that can be directly used for segment registers -// 0 on error -selector_id i386_selector_add( selector_type type ) -{ - static spinlock spinlock; - int state; - uint32 mask; - selector_id id = 0; - unsigned i; - - state = disable_interrupts(); - acquire_spinlock( &spinlock ); - - for ( i = 0; i < ENTRIES; i++ ) - if ( selector_bitmap[i] != 0xffffffff ) { // found free place in there - id = i*sizeof(uint32)*8; - mask = 1; - while ( selector_bitmap[i] & mask ) { - mask <<= 1; - id++; - } - selector_bitmap[i] |= mask; - gdt_table[id] = type; - break; - } - - release_spinlock( &spinlock ); - restore_interrupts( state ); - - if ( id ) { - asm("lgdt %0;" - : : "m" (descr)); - } - - return id*8; -} - -// removes a selector with given id from the gdt -void i386_selector_remove( selector_id id ) -{ - if ( id < 8*8 || id >= MAX_SELECTORS*8 ) - return; - - id /= 8; - gdt_table[id] = 0; - - atomic_and( &selector_bitmap[id/32], ~(1<<(id&31)) ); - - asm("lgdt %0;" - : : "m" (descr)); -} - -// returns the selector type of a given id -selector_type i386_selector_get( selector_id id ) -{ - return gdt_table[id/8]; -} From 4e8fbfb2d158de7b1cadd1c060acee51a7d67309 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 3 Jul 2012 20:55:36 +0100 Subject: [PATCH 060/273] x86_{read,write}_cr{0,4} can just be implemented as macros, put an x86_ prefix on the other read/write macros for consistency. --- headers/private/kernel/arch/x86/arch_cpu.h | 47 ++++++++++++++----- headers/private/kernel/arch/x86/arch_int.h | 4 +- headers/private/kernel/arch/x86/arch_thread.h | 5 +- .../kernel/arch/x86/{arch_x86.S => 32/arch.S} | 26 ---------- src/system/kernel/arch/x86/32/int.cpp | 7 +-- src/system/kernel/arch/x86/64/int.cpp | 5 +- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_cpu.cpp | 2 +- src/system/kernel/arch/x86/arch_debug.cpp | 16 +++---- .../x86/paging/32bit/X86PagingMethod32Bit.cpp | 7 ++- .../paging/32bit/X86PagingStructures32Bit.cpp | 3 +- .../x86/paging/pae/X86PagingMethodPAE.cpp | 9 ++-- 12 files changed, 61 insertions(+), 72 deletions(-) rename src/system/kernel/arch/x86/{arch_x86.S => 32/arch.S} (94%) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index d5e284e006..a70f55de23 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -270,19 +270,46 @@ typedef struct arch_cpu_info { #define nop() __asm__ ("nop"::) -#define read_cr2(value) \ - __asm__("mov %%cr2,%0" : "=r" (value)) +#define x86_read_cr0() ({ \ + size_t _v; \ + __asm__("mov %%cr0,%0" : "=r" (_v)); \ + _v; \ +}) -#define read_cr3(value) \ - __asm__("mov %%cr3,%0" : "=r" (value)) +#define x86_write_cr0(value) \ + __asm__("mov %0,%%cr0" : : "r" (value)) -#define write_cr3(value) \ +#define x86_read_cr2() ({ \ + size_t _v; \ + __asm__("mov %%cr2,%0" : "=r" (_v)); \ + _v; \ +}) + +#define x86_read_cr3() ({ \ + size_t _v; \ + __asm__("mov %%cr3,%0" : "=r" (_v)); \ + _v; \ +}) + +#define x86_write_cr3(value) \ __asm__("mov %0,%%cr3" : : "r" (value)) -#define read_dr3(value) \ - __asm__("mov %%dr3,%0" : "=r" (value)) +#define x86_read_cr4() ({ \ + size_t _v; \ + __asm__("mov %%cr4,%0" : "=r" (_v)); \ + _v; \ +}) -#define write_dr3(value) \ +#define x86_write_cr4(value) \ + __asm__("mov %0,%%cr4" : : "r" (value)) + +#define x86_read_dr3() ({ \ + size_t _v; \ + __asm__("mov %%dr3,%0" : "=r" (_v)); \ + _v; \ +}) + +#define x86_write_dr3(value) \ __asm__("mov %0,%%dr3" : : "r" (value)) #define invalidate_TLB(va) \ @@ -360,10 +387,6 @@ void i386_noop_swap(void* oldFpuState, const void* newFpuState); void i386_fnsave_swap(void* oldFpuState, const void* newFpuState); void i386_fxsave_swap(void* oldFpuState, const void* newFpuState); uint32 x86_read_ebp(); -uint32 x86_read_cr0(); -void x86_write_cr0(uint32 value); -uint32 x86_read_cr4(); -void x86_write_cr4(uint32 value); uint64 x86_read_msr(uint32 registerNumber); void x86_write_msr(uint32 registerNumber, uint64 value); void x86_set_task_gate(int32 cpu, int32 n, int32 segment); diff --git a/headers/private/kernel/arch/x86/arch_int.h b/headers/private/kernel/arch/x86/arch_int.h index f00b56e91e..da4943726d 100644 --- a/headers/private/kernel/arch/x86/arch_int.h +++ b/headers/private/kernel/arch/x86/arch_int.h @@ -21,7 +21,7 @@ arch_int_enable_interrupts_inline(void) static inline int arch_int_disable_interrupts_inline(void) { - unsigned long flags; + size_t flags; asm volatile("pushf;\n" "pop %0;\n" @@ -41,7 +41,7 @@ arch_int_restore_interrupts_inline(int oldState) static inline bool arch_int_are_interrupts_enabled_inline(void) { - unsigned long flags; + size_t flags; asm volatile("pushf;\n" "pop %0;\n" : "=g" (flags)); diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 567d4caff0..cf2bb57034 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -57,8 +57,7 @@ void arch_syscall_64_bit_return_value(void); static inline Thread* arch_thread_get_current_thread(void) { - Thread* t; - read_dr3(t); + Thread* t = (Thread*)x86_read_dr3(); return t; } @@ -66,7 +65,7 @@ arch_thread_get_current_thread(void) static inline void arch_thread_set_current_thread(Thread* t) { - write_dr3(t); + x86_write_dr3(t); } diff --git a/src/system/kernel/arch/x86/arch_x86.S b/src/system/kernel/arch/x86/32/arch.S similarity index 94% rename from src/system/kernel/arch/x86/arch_x86.S rename to src/system/kernel/arch/x86/32/arch.S index 1ebcae0e82..0d256a5512 100644 --- a/src/system/kernel/arch/x86/arch_x86.S +++ b/src/system/kernel/arch/x86/32/arch.S @@ -86,32 +86,6 @@ FUNCTION(x86_read_ebp): ret FUNCTION_END(x86_read_ebp) -/* uint32 x86_read_cr0(); */ -FUNCTION(x86_read_cr0): - movl %cr0, %eax - ret -FUNCTION_END(x86_read_cr0) - -/* void x86_write_cr0(uint32 value); */ -FUNCTION(x86_write_cr0): - movl 4(%esp), %eax - movl %eax, %cr0 - ret -FUNCTION_END(x86_write_cr0) - -/* uint32 x86_read_cr4(); */ -FUNCTION(x86_read_cr4): - movl %cr4, %eax - ret -FUNCTION_END(x86_read_cr4) - -/* void x86_write_cr4(uint32 value); */ -FUNCTION(x86_write_cr4): - movl 4(%esp), %eax - movl %eax, %cr4 - ret -FUNCTION_END(x86_write_cr4) - /* uint64 x86_read_msr(uint32 register); */ FUNCTION(x86_read_msr): movl 4(%esp), %ecx diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index fe54d5800f..d35e3f0c63 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -322,8 +322,7 @@ x86_double_fault_exception(struct iframe* frame) void x86_page_fault_exception_double_fault(struct iframe* frame) { - uint32 cr2; - asm("movl %%cr2, %0" : "=r" (cr2)); + addr_t cr2 = x86_read_cr2(); // Only if this CPU has a fault handler, we're allowed to be here. cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; @@ -351,11 +350,9 @@ static void page_fault_exception(struct iframe* frame) { Thread *thread = thread_get_current_thread(); - uint32 cr2; + addr_t cr2 = x86_read_cr2(); addr_t newip; - asm("movl %%cr2, %0" : "=r" (cr2)); - if (debug_debugger_running()) { // If this CPU or this thread has a fault handler, we're allowed to be // here. diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index d9f3a0a76a..e1ce5e817c 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -53,7 +53,7 @@ extern void hardware_interrupt(struct iframe* frame); static const char* -exception_name(unsigned long number, char* buffer, size_t bufferSize) +exception_name(uint64 number, char* buffer, size_t bufferSize) { if (number >= 0 && number < (sizeof(kInterruptNames) / sizeof(kInterruptNames[0]))) @@ -97,8 +97,7 @@ unexpected_exception(iframe* frame) static void page_fault_exception(iframe* frame) { - unsigned long cr2; - read_cr2(cr2); + addr_t cr2 = x86_read_cr2(); panic("page fault exception at ip %#lx on %#lx, error code %#lx\n", frame->rip, cr2, frame->error_code); diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index c2b29afaaa..d8019117b0 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -28,6 +28,7 @@ if $(TARGET_ARCH) = x86_64 { SEARCH_SOURCE += [ FDirName $(SUBDIR) 32 ] ; archSpecificSources = + arch.S int.cpp interrupts.S @@ -42,7 +43,6 @@ if $(TARGET_ARCH) = x86_64 { arch_timer.cpp arch_vm.cpp arch_vm_translation_map.cpp - arch_x86.S arch_system_info.cpp arch_user_debugger.cpp apic.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 6d5a322218..2617c2e579 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -355,7 +355,7 @@ init_double_fault(int cpuNum) tss->sp0 = (uint32)x86_get_double_fault_stack(cpuNum, &stackSize); tss->sp0 += stackSize; tss->ss0 = KERNEL_DATA_SEG; - read_cr3(tss->cr3); + tss->cr3 = x86_read_cr3(); // copy the current cr3 to the double fault cr3 tss->eip = (uint32)&double_fault; tss->es = KERNEL_DATA_SEG; diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index d3c6b8b1e9..f00cb70f67 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -401,8 +401,8 @@ setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp, thread_get_current_thread(), thread); if (newPageDirectory != 0) { - read_cr3(*_oldPageDirectory); - write_cr3(newPageDirectory); + *_oldPageDirectory = x86_read_cr3(); + x86_write_cr3(newPageDirectory); } if (thread->state == B_THREAD_RUNNING) { @@ -669,7 +669,7 @@ stack_trace(int argc, char **argv) if (oldPageDirectory != 0) { // switch back to the previous page directory to no cause any troubles - write_cr3(oldPageDirectory); + x86_write_cr3(oldPageDirectory); } return 0; @@ -829,7 +829,7 @@ show_call(int argc, char **argv) if (oldPageDirectory != 0) { // switch back to the previous page directory to not cause any troubles - write_cr3(oldPageDirectory); + x86_write_cr3(oldPageDirectory); } return 0; @@ -938,8 +938,8 @@ cmd_in_context(int argc, char** argv) thread_get_current_thread(), thread); if (newPageDirectory != 0) { - read_cr3(oldPageDirectory); - write_cr3(newPageDirectory); + oldPageDirectory = x86_read_cr3(); + x86_write_cr3(newPageDirectory); } } @@ -951,7 +951,7 @@ cmd_in_context(int argc, char** argv) // reset the page directory if (oldPageDirectory) - write_cr3(oldPageDirectory); + x86_write_cr3(oldPageDirectory); return 0; } @@ -1128,7 +1128,7 @@ arch_debug_get_interrupt_pc(bool* _isSyscall) void arch_debug_unset_current_thread(void) { - write_dr3(NULL); + x86_write_dr3(NULL); } diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp index 674c4b5a60..ad0c812357 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp @@ -419,9 +419,8 @@ X86PagingMethod32Bit::IsKernelPageAccessible(addr_t virtualAddress, { // We only trust the kernel team's page directory. So switch to it first. // Always set it to make sure the TLBs don't contain obsolete data. - uint32 physicalPageDirectory; - read_cr3(physicalPageDirectory); - write_cr3(fKernelPhysicalPageDirectory); + uint32 physicalPageDirectory = x86_read_cr3(); + x86_write_cr3(fKernelPhysicalPageDirectory); // get the page directory entry for the address page_directory_entry pageDirectoryEntry; @@ -465,7 +464,7 @@ X86PagingMethod32Bit::IsKernelPageAccessible(addr_t virtualAddress, // switch back to the original page directory if (physicalPageDirectory != fKernelPhysicalPageDirectory) - write_cr3(physicalPageDirectory); + x86_write_cr3(physicalPageDirectory); if ((pageTableEntry & X86_PTE_PRESENT) == 0) return false; diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingStructures32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86PagingStructures32Bit.cpp index 4b86a85611..3538951466 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingStructures32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingStructures32Bit.cpp @@ -100,8 +100,7 @@ X86PagingStructures32Bit::Delete() #if 0 // this sanity check can be enabled when corruption due to // overwriting an active page directory is suspected - uint32 activePageDirectory; - read_cr3(activePageDirectory); + uint32 activePageDirectory = x86_read_cr3(); if (activePageDirectory == pgdir_phys) panic("deleting a still active page directory\n"); #endif diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp index 280dd143cb..4156b3ad33 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp @@ -163,7 +163,7 @@ struct X86PagingMethodPAE::ToPAESwitcher { private: static void _EnablePAE(void* physicalPDPT, int cpu) { - write_cr3((addr_t)physicalPDPT); + x86_write_cr3((addr_t)physicalPDPT); x86_write_cr4(x86_read_cr4() | IA32_CR4_PAE | IA32_CR4_GLOBAL_PAGES); } @@ -681,9 +681,8 @@ X86PagingMethodPAE::IsKernelPageAccessible(addr_t virtualAddress, // We only trust the kernel team's page directories. So switch to the // kernel PDPT first. Always set it to make sure the TLBs don't contain // obsolete data. - uint32 physicalPDPT; - read_cr3(physicalPDPT); - write_cr3(fKernelPhysicalPageDirPointerTable); + uint32 physicalPDPT = x86_read_cr3(); + x86_write_cr3(fKernelPhysicalPageDirPointerTable); // get the PDPT entry for the address pae_page_directory_pointer_table_entry pdptEntry = 0; @@ -734,7 +733,7 @@ X86PagingMethodPAE::IsKernelPageAccessible(addr_t virtualAddress, // switch back to the original page directory if (physicalPDPT != fKernelPhysicalPageDirPointerTable) - write_cr3(physicalPDPT); + x86_write_cr3(physicalPDPT); if ((pageTableEntry & X86_PAE_PTE_PRESENT) == 0) return false; From 4304bb9894335fe5e5bd667a1f27dc7605c2e5b9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 14:06:46 +0100 Subject: [PATCH 061/273] Added arch_cpu.cpp to the x86_64 build. * Some things are currently ifndef'd out completely for x86_64 because they aren't implemented, there's a few other ifdef's to handle x86_64 differences but most of the code works unchanged. * Renamed some i386_* functions to x86_*. * Added a temporary method for setting the current thread on x86_64 (a global variable, not SMP safe). This will be changed to be done via the GS segment but I've not implemented that yet. --- headers/os/kernel/OS.h | 2 +- .../private/kernel/arch/x86/32/descriptors.h | 7 +- .../private/kernel/arch/x86/64/descriptors.h | 4 +- headers/private/kernel/arch/x86/arch_cpu.h | 32 ++--- .../kernel/arch/x86/arch_system_info.h | 6 +- headers/private/kernel/arch/x86/arch_thread.h | 8 +- src/system/boot/arch/x86/Jamfile | 6 + src/system/kernel/arch/x86/32/arch.S | 55 +++---- src/system/kernel/arch/x86/{ => 32}/cpuid.S | 0 src/system/kernel/arch/x86/64/arch.S | 66 +++++++++ src/system/kernel/arch/x86/64/cpuid.S | 45 ++++++ src/system/kernel/arch/x86/64/int.cpp | 9 ++ src/system/kernel/arch/x86/64/stubs.cpp | 102 +------------ src/system/kernel/arch/x86/Jamfile | 6 +- src/system/kernel/arch/x86/arch_cpu.cpp | 136 ++++++++++++------ src/system/kernel/arch/x86/arch_thread.cpp | 8 +- .../kernel/arch/x86/arch_user_debugger.cpp | 10 +- 17 files changed, 291 insertions(+), 211 deletions(-) rename src/system/kernel/arch/x86/{ => 32}/cpuid.S (100%) create mode 100644 src/system/kernel/arch/x86/64/arch.S create mode 100644 src/system/kernel/arch/x86/64/cpuid.S diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 1f921f98ed..c3fe2b0261 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -645,7 +645,7 @@ typedef enum cpu_types { #define B_CPU_x86_VENDOR_MASK 0xff00 -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64) typedef union { struct { uint32 max_eax; diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h index d57bf05da5..c578acfd16 100644 --- a/headers/private/kernel/arch/x86/32/descriptors.h +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -26,10 +26,11 @@ // (and is in arch_interrupts.S) #define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 -#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) +#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) +#define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu) // defines entries in the GDT/LDT diff --git a/headers/private/kernel/arch/x86/64/descriptors.h b/headers/private/kernel/arch/x86/64/descriptors.h index 7e5efb9c83..8e70cba67e 100644 --- a/headers/private/kernel/arch/x86/64/descriptors.h +++ b/headers/private/kernel/arch/x86/64/descriptors.h @@ -18,7 +18,7 @@ #define TSS_BASE_SEGMENT 5 -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) +#define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu * 2) // Structure of a segment descriptor. @@ -89,7 +89,7 @@ struct tss { uint64 ist7; uint64 _reserved3; uint16 _reserved4; - uint16 io_bitmap; + uint16 io_map_base; } _PACKED; diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index a70f55de23..f688a206cb 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -365,12 +365,9 @@ typedef struct arch_cpu_info { extern "C" { #endif - -// temporary -#ifndef __x86_64__ - struct arch_thread; + void __x86_setup_system_time(uint32 conversionFactor, uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); void x86_context_switch(struct arch_thread* oldState, @@ -378,18 +375,12 @@ void x86_context_switch(struct arch_thread* oldState, void x86_userspace_thread_exit(void); void x86_end_userspace_thread_exit(void); void x86_swap_pgdir(uint32 newPageDir); -void i386_set_tss_and_kstack(addr_t kstack); -void i386_fnsave(void* fpuState); -void i386_fxsave(void* fpuState); -void i386_frstor(const void* fpuState); -void i386_fxrstor(const void* fpuState); -void i386_noop_swap(void* oldFpuState, const void* newFpuState); -void i386_fnsave_swap(void* oldFpuState, const void* newFpuState); -void i386_fxsave_swap(void* oldFpuState, const void* newFpuState); -uint32 x86_read_ebp(); +void x86_fxsave(void* fpuState); +void x86_fxrstor(const void* fpuState); +void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); +addr_t x86_read_ebp(); uint64 x86_read_msr(uint32 registerNumber); void x86_write_msr(uint32 registerNumber, uint64 value); -void x86_set_task_gate(int32 cpu, int32 n, int32 segment); void* x86_get_idt(int32 cpu); uint32 x86_count_mtrrs(void); void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); @@ -400,16 +391,23 @@ void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos, void x86_init_fpu(); bool x86_check_feature(uint32 feature, enum x86_feature_type type); void* x86_get_double_fault_stack(int32 cpu, size_t* _size); -int32 x86_double_fault_get_cpu(void); void x86_double_fault_exception(struct iframe* frame); void x86_page_fault_exception_double_fault(struct iframe* frame); +#ifndef __x86_64__ + +void i386_set_tss_and_kstack(addr_t kstack); +void x86_fnsave(void* fpuState); +void x86_frstor(const void* fpuState); +void x86_noop_swap(void* oldFpuState, const void* newFpuState); +void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); +void x86_set_task_gate(int32 cpu, int32 n, int32 segment); +int32 x86_double_fault_get_cpu(void); + #endif - extern segment_descriptor* gGDT; - #ifdef __cplusplus } // extern "C" { #endif diff --git a/headers/private/kernel/arch/x86/arch_system_info.h b/headers/private/kernel/arch/x86/arch_system_info.h index 88b018d370..b8a7383de9 100644 --- a/headers/private/kernel/arch/x86/arch_system_info.h +++ b/headers/private/kernel/arch/x86/arch_system_info.h @@ -12,13 +12,11 @@ extern "C" { #endif -#ifndef __x86_64__ -status_t get_current_cpuid(cpuid_info *info, uint32 eax); +status_t get_current_cpuid(cpuid_info* info, uint32 eax); uint32 get_eflags(void); void set_eflags(uint32 value); -status_t _user_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); -#endif +status_t _user_get_cpuid(cpuid_info* info, uint32 eax, uint32 cpu); #ifdef __cplusplus } diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index cf2bb57034..7efd8b11e8 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -30,19 +30,21 @@ void x86_set_tls_context(Thread* thread); #ifdef __x86_64__ - // TODO + +extern Thread* gCurrentThread; + static inline Thread* arch_thread_get_current_thread(void) { - return NULL; + return gCurrentThread; } static inline void arch_thread_set_current_thread(Thread* t) { - + gCurrentThread = t; } diff --git a/src/system/boot/arch/x86/Jamfile b/src/system/boot/arch/x86/Jamfile index f373212aa7..0fd15d01f3 100644 --- a/src/system/boot/arch/x86/Jamfile +++ b/src/system/boot/arch/x86/Jamfile @@ -4,6 +4,9 @@ DEFINES += _BOOT_MODE ; local kernelArchSources = arch_elf.cpp +; + +local kernelArch32Sources = cpuid.S ; @@ -17,6 +20,7 @@ local librootOsArchSources = BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : $(kernelArchSources) + $(kernelArch32Sources) $(kernelLibArchSources) $(librootOsArchSources) : # additional flags @@ -24,6 +28,8 @@ BootMergeObject boot_arch_$(TARGET_KERNEL_ARCH).o : SEARCH on [ FGristFiles $(kernelArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel arch x86 ] ; +SEARCH on [ FGristFiles $(kernelArch32Sources) ] + = [ FDirName $(HAIKU_TOP) src system kernel arch x86 32 ] ; SEARCH on [ FGristFiles $(kernelLibArchSources) ] = [ FDirName $(HAIKU_TOP) src system kernel lib arch x86 ] ; SEARCH on [ FGristFiles $(librootOsArchSources) ] diff --git a/src/system/kernel/arch/x86/32/arch.S b/src/system/kernel/arch/x86/32/arch.S index 0d256a5512..e966580dbe 100644 --- a/src/system/kernel/arch/x86/32/arch.S +++ b/src/system/kernel/arch/x86/32/arch.S @@ -19,66 +19,57 @@ .text -/*! \fn void arch_cpu_user_TLB_invalidate() - Invalidates the TLB. Must be called with interrupts disabled. -*/ -FUNCTION(arch_cpu_user_TLB_invalidate): - movl %cr3, %eax - movl %eax, %cr3 - ret -FUNCTION_END(arch_cpu_user_TLB_invalidate) - -/* void i386_fnsave(void *fpu_state); */ -FUNCTION(i386_fnsave): +/* void x86_fnsave(void *fpu_state); */ +FUNCTION(x86_fnsave): movl 4(%esp), %eax fnsave (%eax) ret -FUNCTION_END(i386_fnsave) +FUNCTION_END(x86_fnsave) -/* void i386_fxsave(void *fpu_state); */ -FUNCTION(i386_fxsave): +/* void x86_fxsave(void *fpu_state); */ +FUNCTION(x86_fxsave): movl 4(%esp), %eax fxsave (%eax) ret -FUNCTION_END(i386_fxsave) +FUNCTION_END(x86_fxsave) -/* void i386_frstor(const void *fpu_state); */ -FUNCTION(i386_frstor): +/* void x86_frstor(const void *fpu_state); */ +FUNCTION(x86_frstor): movl 4(%esp), %eax frstor (%eax) ret -FUNCTION_END(i386_frstor) +FUNCTION_END(x86_frstor) -/* void i386_fxrstor(const void *fpu_state); */ -FUNCTION(i386_fxrstor): +/* void x86_fxrstor(const void *fpu_state); */ +FUNCTION(x86_fxrstor): movl 4(%esp), %eax fxrstor (%eax) ret -FUNCTION_END(i386_fxrstor) +FUNCTION_END(x86_fxrstor) -/* void i386_noop_swap(void *old_fpu_state, const void *new_fpu_state); */ -FUNCTION(i386_noop_swap): +/* void x86_noop_swap(void *old_fpu_state, const void *new_fpu_state); */ +FUNCTION(x86_noop_swap): nop ret -FUNCTION_END(i386_noop_swap) +FUNCTION_END(x86_noop_swap) -/* void i386_fsave_swap(void *old_fpu_state, const void *new_fpu_state); */ -FUNCTION(i386_fnsave_swap): +/* void x86_fnsave_swap(void *old_fpu_state, const void *new_fpu_state); */ +FUNCTION(x86_fnsave_swap): movl 4(%esp),%eax fnsave (%eax) movl 8(%esp),%eax frstor (%eax) ret -FUNCTION_END(i386_fnsave_swap) +FUNCTION_END(x86_fnsave_swap) -/* void i386_fxsave_swap(void *old_fpu_state, const void *new_fpu_state); */ -FUNCTION(i386_fxsave_swap): +/* void x86_fxsave_swap(void *old_fpu_state, const void *new_fpu_state); */ +FUNCTION(x86_fxsave_swap): movl 4(%esp),%eax fxsave (%eax) movl 8(%esp),%eax fxrstor (%eax) ret -FUNCTION_END(i386_fxsave_swap) +FUNCTION_END(x86_fxsave_swap) /* uint32 x86_read_ebp(); */ FUNCTION(x86_read_ebp): @@ -142,12 +133,12 @@ null_idt_descr: .word 0 .word 0,0 -FUNCTION(reboot): +FUNCTION(x86_reboot): lidt null_idt_descr int $0 done: jmp done -FUNCTION_END(reboot) +FUNCTION_END(x86_reboot) /* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ diff --git a/src/system/kernel/arch/x86/cpuid.S b/src/system/kernel/arch/x86/32/cpuid.S similarity index 100% rename from src/system/kernel/arch/x86/cpuid.S rename to src/system/kernel/arch/x86/32/cpuid.S diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S new file mode 100644 index 0000000000..fcf7d26916 --- /dev/null +++ b/src/system/kernel/arch/x86/64/arch.S @@ -0,0 +1,66 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +.text + + +/* void x86_fxsave(void* fpuState); */ +FUNCTION(x86_fxsave): + fxsave (%rdi) + ret +FUNCTION_END(x86_fxsave) + + +/* void x86_fxrstor(const void* fpuState); */ +FUNCTION(x86_fxrstor): + fxrstor (%rdi) + ret +FUNCTION_END(x86_fxrstor) + + +/* void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); */ +FUNCTION(x86_fxsave_swap): + fxsave (%rdi) + fxrstor (%rsi) + ret +FUNCTION_END(x86_fxsave_swap) + + +/* uint64 x86_read_msr(uint32 register); */ +FUNCTION(x86_read_msr): + mov %edi, %ecx + rdmsr + shl $32, %rdx + mov %eax, %eax + or %rdx, %rax + ret +FUNCTION_END(x86_read_msr) + + +/* void x86_write_msr(uint32 register, uint64 value); */ +FUNCTION(x86_write_msr): + mov %rsi, %rdx + mov %esi, %eax + mov %edi, %ecx + shr $32, %rdx + wrmsr + ret +FUNCTION_END(x86_write_msr) + + +null_idt_descr: + .word 0 + .quad 0 + +FUNCTION(x86_reboot): + lidt null_idt_descr + int $0 +done: + jmp done +FUNCTION_END(x86_reboot) diff --git a/src/system/kernel/arch/x86/64/cpuid.S b/src/system/kernel/arch/x86/64/cpuid.S new file mode 100644 index 0000000000..8e6b07cd6b --- /dev/null +++ b/src/system/kernel/arch/x86/64/cpuid.S @@ -0,0 +1,45 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +.text + + +/* status_t get_current_cpuid(cpuid_info* info, uint32 eaxRegister) */ +FUNCTION(get_current_cpuid): + push %rbx + movl %esi, %eax + cpuid + movl %eax, 0(%rdi) + movl %ebx, 4(%rdi) + movl %edx, 8(%rdi) + movl %ecx, 12(%rdi) + xorl %eax, %eax + // B_OK + pop %rbx + ret +FUNCTION_END(get_current_cpuid) + + +/* uint32 get_eflags(void) */ +FUNCTION(get_eflags): + // The top 32 bits of RFLAGS are reserved, we can ignore them. + pushf + pop %rax + mov %eax, %eax + ret +FUNCTION_END(get_eflags) + + +/* void set_eflags(uint32 val) */ +FUNCTION(set_eflags): + mov %edi, %edi + push %rdi + popf + ret +FUNCTION_END(set_eflags) diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index e1ce5e817c..04671a5dd2 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -104,6 +104,15 @@ page_fault_exception(iframe* frame) } +/*! Returns the virtual IDT address for CPU \a cpu. */ +void* +x86_get_idt(int32 cpu) +{ + // We use a single IDT for all CPUs on x86_64. + return sIDT; +} + + // #pragma mark - diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 299c6fc648..281948e1a0 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -37,6 +37,10 @@ #include +// temporary +Thread* gCurrentThread = NULL; + + status_t arch_commpage_init(void) { @@ -51,69 +55,6 @@ arch_commpage_init_post_cpus(void) } -status_t -arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) -{ - return B_OK; -} - - -status_t -arch_cpu_init_percpu(kernel_args* args, int cpu) -{ - return B_OK; -} - - -status_t -arch_cpu_init(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_cpu_init_post_vm(kernel_args* args) -{ - return B_OK; -} - - -status_t -arch_cpu_init_post_modules(kernel_args* args) -{ - return B_OK; -} - - -void -arch_cpu_user_TLB_invalidate(void) -{ - -} - - -void -arch_cpu_global_TLB_invalidate(void) -{ - -} - - -void -arch_cpu_invalidate_TLB_range(addr_t start, addr_t end) -{ - -} - - -void -arch_cpu_invalidate_TLB_list(addr_t pages[], int num_pages) -{ - -} - - ssize_t arch_cpu_user_strlcpy(char* to, const char* from, size_t size, addr_t* faultHandler) @@ -137,41 +78,6 @@ arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) } -status_t -arch_cpu_shutdown(bool rebootSystem) -{ - return B_ERROR; -} - - -void -arch_cpu_idle(void) -{ - asm("hlt"); -} - - -void -arch_cpu_sync_icache(void* address, size_t length) -{ - // Instruction cache is always consistent on x86. -} - - -void -arch_cpu_memory_read_barrier(void) -{ - asm volatile("lfence" : : : "memory"); -} - - -void -arch_cpu_memory_write_barrier(void) -{ - asm volatile("sfence" : : : "memory"); -} - - void arch_debug_save_registers(struct arch_debug_registers* registers) { diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index d8019117b0..7502f4d3e4 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -20,6 +20,8 @@ if $(TARGET_ARCH) = x86_64 { SEARCH_SOURCE += [ FDirName $(SUBDIR) 64 ] ; archSpecificSources = + arch.S + cpuid.S int.cpp interrupts.S stubs.cpp @@ -29,11 +31,11 @@ if $(TARGET_ARCH) = x86_64 { archSpecificSources = arch.S + cpuid.S int.cpp interrupts.S arch_commpage.cpp - arch_cpu.cpp arch_debug.cpp arch_elf.cpp arch_platform.cpp @@ -48,7 +50,6 @@ if $(TARGET_ARCH) = x86_64 { apic.cpp apm.cpp bios.cpp - cpuid.S ioapic.cpp irq_routing_table.cpp msi.cpp @@ -83,6 +84,7 @@ if $(TARGET_ARCH) = x86_64 { } local archGenericSources = + arch_cpu.cpp arch_debug_console.cpp arch_int.cpp pic.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 2617c2e579..ff0e971da4 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1,5 +1,6 @@ /* * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -30,10 +31,13 @@ #include #include -#include "interrupts.h" #include "paging/X86PagingStructures.h" #include "paging/X86VMTranslationMap.h" +#ifndef __x86_64__ +#include "32/interrupts.h" +#endif + #define DUMP_FEATURE_STRING 1 @@ -83,25 +87,27 @@ struct set_mtrrs_parameter { }; -extern "C" void reboot(void); - // from arch_x86.S +extern "C" void x86_reboot(void); + // from arch.S -void (*gX86SwapFPUFunc)(void *oldState, const void *newState); void (*gCpuIdleFunc)(void); +#ifndef __x86_64__ +void (*gX86SwapFPUFunc)(void* oldState, const void* newState) = x86_noop_swap; bool gHasSSE = false; +#endif static uint32 sCpuRendezvous; static uint32 sCpuRendezvous2; static uint32 sCpuRendezvous3; static vint32 sTSCSyncRendezvous; -segment_descriptor *gGDT = NULL; +segment_descriptor* gGDT = NULL; /* Some specials for the double fault handler */ static uint8* sDoubleFaultStacks; static const size_t kDoubleFaultStackSize = 4096; // size per CPU -static x86_cpu_module_info *sCpuModule; +static x86_cpu_module_info* sCpuModule; extern "C" void memcpy_generic(void* dest, const void* source, size_t count); @@ -109,12 +115,15 @@ extern int memcpy_generic_end; extern "C" void memset_generic(void* dest, int value, size_t count); extern int memset_generic_end; +// TODO x86_64 +#ifndef __x86_64__ x86_optimized_functions gOptimizedFunctions = { memcpy_generic, &memcpy_generic_end, memset_generic, &memset_generic_end }; +#endif static status_t @@ -176,10 +185,10 @@ enable_caches() static void -set_mtrr(void *_parameter, int cpu) +set_mtrr(void* _parameter, int cpu) { - struct set_mtrr_parameter *parameter - = (struct set_mtrr_parameter *)_parameter; + struct set_mtrr_parameter* parameter + = (struct set_mtrr_parameter*)_parameter; // wait until all CPUs have arrived here smp_cpu_rendezvous(&sCpuRendezvous, cpu); @@ -233,7 +242,7 @@ set_mtrrs(void* _parameter, int cpu) static void -init_mtrrs(void *_unused, int cpu) +init_mtrrs(void* _unused, int cpu) { // wait until all CPUs have arrived here smp_cpu_rendezvous(&sCpuRendezvous, cpu); @@ -282,7 +291,7 @@ x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type) status_t -x86_get_mtrr(uint32 index, uint64 *_base, uint64 *_length, uint8 *_type) +x86_get_mtrr(uint32 index, uint64* _base, uint64* _length, uint8* _type) { // the MTRRs are identical on all CPUs, so it doesn't matter // on which CPU this runs @@ -309,10 +318,12 @@ x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos, uint32 count) void x86_init_fpu(void) { + // All x86_64 CPUs support SSE, don't need to bother checking for it. +#ifndef __x86_64__ if (!x86_check_feature(IA32_FEATURE_FPU, FEATURE_COMMON)) { // No FPU... time to install one in your 386? dprintf("%s: Warning: CPU has no reported FPU.\n", __func__); - gX86SwapFPUFunc = i386_noop_swap; + gX86SwapFPUFunc = x86_noop_swap; return; } @@ -321,17 +332,21 @@ x86_init_fpu(void) dprintf("%s: CPU has no SSE... just enabling FPU.\n", __func__); // we don't have proper SSE support, just enable FPU x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); - gX86SwapFPUFunc = i386_fnsave_swap; + gX86SwapFPUFunc = x86_fnsave_swap; return; } +#endif + dprintf("%s: CPU has SSE... enabling FXSR and XMM.\n", __func__); // enable OS support for SSE x86_write_cr4(x86_read_cr4() | CR4_OS_FXSR | CR4_OS_XMM_EXCEPTION); x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); - gX86SwapFPUFunc = i386_fxsave_swap; +#ifndef __x86_64__ + gX86SwapFPUFunc = x86_fxsave_swap; gHasSSE = true; +#endif } @@ -339,20 +354,27 @@ static void load_tss(int cpu) { short seg = ((TSS_BASE_SEGMENT + cpu) << 3) | DPL_KERNEL; - asm("movw %0, %%ax;" - "ltr %%ax;" : : "r" (seg) : "eax"); + asm("ltr %%ax" : : "a" (seg)); } static void init_double_fault(int cpuNum) { +#ifdef __x86_64__ + // x86_64 does not have task gates, so we use the IST mechanism to switch + // to the double fault stack upon a double fault (see 64/int.cpp). + struct tss* tss = &gCPU[cpuNum].arch.tss; + size_t stackSize; + tss->ist1 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize); + tss->ist1 += stackSize; +#else // set up the double fault TSS - struct tss *tss = &gCPU[cpuNum].arch.double_fault_tss; + struct tss* tss = &gCPU[cpuNum].arch.double_fault_tss; memset(tss, 0, sizeof(struct tss)); size_t stackSize; - tss->sp0 = (uint32)x86_get_double_fault_stack(cpuNum, &stackSize); + tss->sp0 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize); tss->sp0 += stackSize; tss->ss0 = KERNEL_DATA_SEG; tss->cr3 = x86_read_cr3(); @@ -374,12 +396,13 @@ init_double_fault(int cpuNum) (addr_t)tss, sizeof(struct tss)); x86_set_task_gate(cpuNum, 8, tssSegmentDescriptorIndex << 3); +#endif } #if DUMP_FEATURE_STRING static void -dump_feature_string(int currentCPU, cpu_ent *cpu) +dump_feature_string(int currentCPU, cpu_ent* cpu) { char features[256]; features[0] = 0; @@ -541,7 +564,7 @@ dump_feature_string(int currentCPU, cpu_ent *cpu) static int detect_cpu(int currentCPU) { - cpu_ent *cpu = get_cpu_struct(); + cpu_ent* cpu = get_cpu_struct(); char vendorString[17]; cpuid_info cpuid; @@ -656,7 +679,7 @@ detect_cpu(int currentCPU) bool x86_check_feature(uint32 feature, enum x86_feature_type type) { - cpu_ent *cpu = get_cpu_struct(); + cpu_ent* cpu = get_cpu_struct(); #if 0 int i; @@ -678,6 +701,7 @@ x86_get_double_fault_stack(int32 cpu, size_t* _size) } +#ifndef __x86_64__ /*! Returns the index of the current CPU. Can only be called from the double fault handler. */ @@ -687,17 +711,15 @@ x86_double_fault_get_cpu(void) uint32 stack = x86_read_ebp(); return (stack - (uint32)sDoubleFaultStacks) / kDoubleFaultStackSize; } +#endif // #pragma mark - status_t -arch_cpu_preboot_init_percpu(kernel_args *args, int cpu) +arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) { - // A simple nop FPU call until x86_init_fpu - gX86SwapFPUFunc = i386_noop_swap; - // On SMP system we want to synchronize the CPUs' TSCs, so system_time() // will return consistent values. if (smp_get_num_cpus() > 1) { @@ -744,7 +766,7 @@ amdc1e_noarat_idle(void) static bool detect_amdc1e_noarat() { - cpu_ent *cpu = get_cpu_struct(); + cpu_ent* cpu = get_cpu_struct(); if (cpu->arch.vendor != VENDOR_AMD) return false; @@ -759,7 +781,7 @@ detect_amdc1e_noarat() status_t -arch_cpu_init_percpu(kernel_args *args, int cpu) +arch_cpu_init_percpu(kernel_args* args, int cpu) { detect_cpu(cpu); @@ -791,7 +813,7 @@ arch_cpu_init_percpu(kernel_args *args, int cpu) status_t -arch_cpu_init(kernel_args *args) +arch_cpu_init(kernel_args* args) { // init the TSC -> system_time() conversion factors @@ -812,13 +834,13 @@ arch_cpu_init(kernel_args *args) status_t -arch_cpu_init_post_vm(kernel_args *args) +arch_cpu_init_post_vm(kernel_args* args) { uint32 i; // account for the segment descriptors - gGDT = (segment_descriptor *)(addr_t)args->arch_args.vir_gdt; - create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, + gGDT = (segment_descriptor*)(addr_t)args->arch_args.vir_gdt; + create_area("gdt", (void**)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); // allocate an area for the double fault stacks @@ -831,41 +853,53 @@ arch_cpu_init_post_vm(kernel_args *args) &virtualRestrictions, &physicalRestrictions, (void**)&sDoubleFaultStacks); + // TODO x86_64 +#ifndef __x86_64__ X86PagingStructures* kernelPagingStructures = static_cast( VMAddressSpace::Kernel()->TranslationMap())->PagingStructures(); +#endif // setup task-state segments for (i = 0; i < args->num_cpus; i++) { // initialize the regular and double fault tss stored in the per-cpu // structure memset(&gCPU[i].arch.tss, 0, sizeof(struct tss)); +#ifndef __x86_64__ gCPU[i].arch.tss.ss0 = KERNEL_DATA_SEG; +#endif gCPU[i].arch.tss.io_map_base = sizeof(struct tss); // add TSS descriptor for this new TSS - set_tss_descriptor(&gGDT[TSS_BASE_SEGMENT + i], - (addr_t)&gCPU[i].arch.tss, sizeof(struct tss)); + set_tss_descriptor(&gGDT[TSS_SEGMENT(i)], (addr_t)&gCPU[i].arch.tss, + sizeof(struct tss)); // initialize the double fault tss init_double_fault(i); + // TODO x86_64 +#ifndef __x86_64__ // init active translation map gCPU[i].arch.active_paging_structures = kernelPagingStructures; kernelPagingStructures->AddReference(); +#endif } // set the current hardware task on cpu 0 load_tss(0); +#ifndef __x86_64__ // setup TLS descriptors (one for every CPU) - for (i = 0; i < args->num_cpus; i++) { set_segment_descriptor(&gGDT[TLS_BASE_SEGMENT + i], 0, TLS_SIZE, DT_DATA_WRITEABLE, DPL_USER); } +#endif + // TODO x86_64 +#ifndef __x86_64 if (!apic_available()) +#endif x86_init_fpu(); // else fpu gets set up in smp code @@ -874,18 +908,18 @@ arch_cpu_init_post_vm(kernel_args *args) status_t -arch_cpu_init_post_modules(kernel_args *args) +arch_cpu_init_post_modules(kernel_args* args) { // initialize CPU module - void *cookie = open_module_list("cpu"); + void* cookie = open_module_list("cpu"); while (true) { char name[B_FILE_NAME_LENGTH]; size_t nameLength = sizeof(name); if (read_next_module_name(cookie, name, &nameLength) != B_OK - || get_module(name, (module_info **)&sCpuModule) == B_OK) + || get_module(name, (module_info**)&sCpuModule) == B_OK) break; } @@ -897,6 +931,8 @@ arch_cpu_init_post_modules(kernel_args *args) call_all_cpus(&init_mtrrs, NULL); } + // TODO x86_64 +#ifndef __x86_64__ // get optimized functions from the CPU module if (sCpuModule != NULL && sCpuModule->get_optimized_functions != NULL) { x86_optimized_functions functions; @@ -933,16 +969,25 @@ arch_cpu_init_post_modules(kernel_args *args) elf_add_memory_image_symbol(image, "commpage_memset", ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_MEMSET], memsetLen, B_SYMBOL_TYPE_TEXT); - +#endif return B_OK; } +#ifndef __x86_64__ void i386_set_tss_and_kstack(addr_t kstack) { get_cpu_struct()->arch.tss.sp0 = kstack; } +#endif + + +void +arch_cpu_user_TLB_invalidate(void) +{ + x86_write_cr3(x86_read_cr3()); +} void @@ -990,8 +1035,11 @@ arch_cpu_shutdown(bool rebootSystem) if (acpi_shutdown(rebootSystem) == B_OK) return B_OK; + // TODO x86_64 +#ifndef __x86_64 if (!rebootSystem) return apm_shutdown(); +#endif cpu_status state = disable_interrupts(); @@ -1002,7 +1050,7 @@ arch_cpu_shutdown(bool rebootSystem) snooze(500000); // if that didn't help, try it this way - reboot(); + x86_reboot(); restore_interrupts(state); return B_ERROR; @@ -1017,7 +1065,7 @@ arch_cpu_idle(void) void -arch_cpu_sync_icache(void *address, size_t length) +arch_cpu_sync_icache(void* address, size_t length) { // instruction cache is always consistent on x86 } @@ -1026,15 +1074,23 @@ arch_cpu_sync_icache(void *address, size_t length) void arch_cpu_memory_read_barrier(void) { +#ifdef __x86_64__ + asm volatile("lfence" : : : "memory"); +#else asm volatile ("lock;" : : : "memory"); asm volatile ("addl $0, 0(%%esp);" : : : "memory"); +#endif } void arch_cpu_memory_write_barrier(void) { +#ifdef __x86_64__ + asm volatile("sfence" : : : "memory"); +#else asm volatile ("lock;" : : : "memory"); asm volatile ("addl $0, 0(%%esp);" : : : "memory"); +#endif } diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index 69ca734eb4..ce482bac49 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -86,9 +86,9 @@ arch_thread_init(struct kernel_args *args) asm volatile ("clts; fninit; fnclex;"); if (gHasSSE) - i386_fxsave(sInitialState.fpu_state); + x86_fxsave(sInitialState.fpu_state); else - i386_fnsave(sInitialState.fpu_state); + x86_fnsave(sInitialState.fpu_state); return B_OK; } @@ -536,7 +536,7 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action, signalFrameData->context.uc_mcontext.edi = frame->edi; signalFrameData->context.uc_mcontext.esi = frame->esi; signalFrameData->context.uc_mcontext.ebx = frame->ebx; - i386_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); + x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); // fill in signalFrameData->context.uc_stack signal_get_user_stack(frame->user_esp, &signalFrameData->context.uc_stack); @@ -605,7 +605,7 @@ arch_restore_signal_frame(struct signal_frame_data* signalFrameData) frame->esi = signalFrameData->context.uc_mcontext.esi; frame->ebx = signalFrameData->context.uc_mcontext.ebx; - i386_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); + x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); TRACE(("### arch_restore_signal_frame: exit\n")); diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp b/src/system/kernel/arch/x86/arch_user_debugger.cpp index 3a2673c367..42aaf6f073 100644 --- a/src/system/kernel/arch/x86/arch_user_debugger.cpp +++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp @@ -596,10 +596,10 @@ arch_set_debug_cpu_state(const debug_cpu_state *cpuState) InterruptsLocker locker; memcpy(thread->arch_info.fpu_state, &cpuState->extended_registers, sizeof(cpuState->extended_registers)); - i386_fxrstor(thread->arch_info.fpu_state); + x86_fxrstor(thread->arch_info.fpu_state); } else { // TODO: Implement! We need to convert the format first. -// i386_frstor(&cpuState->extended_registers); +// x86_frstor(&cpuState->extended_registers); } // frame->gs = cpuState->gs; @@ -638,13 +638,13 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState) // buffer. We need to disable interrupts to make use of it. Thread* thread = thread_get_current_thread(); InterruptsLocker locker; - i386_fxsave(thread->arch_info.fpu_state); + x86_fxsave(thread->arch_info.fpu_state); // unlike fnsave, fxsave doesn't reinit the FPU state memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state, sizeof(cpuState->extended_registers)); } else { - i386_fnsave(&cpuState->extended_registers); - i386_frstor(&cpuState->extended_registers); + x86_fnsave(&cpuState->extended_registers); + x86_frstor(&cpuState->extended_registers); // fnsave reinits the FPU state after saving, so we need to // load it again // TODO: Convert to fxsave format! From 428b9e758c30a95154f5ad0d974894ef9ae133d6 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 14:23:35 +0100 Subject: [PATCH 062/273] Check whether gX86PagingMethod is NULL in arch_vm_translation_map_is_kernel_page_accessible. This means that the kernel debugger won't cause a recursive panic if a panic occurs before vm_init(). --- src/system/kernel/arch/x86/arch_vm_translation_map.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index aa20762e29..af3d64b248 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -144,5 +144,8 @@ bool arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, uint32 protection) { + if (!gX86PagingMethod) + return true; + return gX86PagingMethod->IsKernelPageAccessible(virtualAddress, protection); } From 4988ca58a0b6f12e48286fe17ee651be490e0f24 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 14:55:11 +0100 Subject: [PATCH 063/273] Build arch_vm.cpp for x86_64. No changes required except for temporarily disabling bios_init call. --- src/system/kernel/arch/x86/64/stubs.cpp | 57 ------------------------- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_vm.cpp | 5 +++ 3 files changed, 6 insertions(+), 58 deletions(-) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 281948e1a0..348887c54c 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -479,63 +479,6 @@ x86_init_user_debug() } -status_t -arch_vm_init(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_post_area(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_end(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_init_post_modules(kernel_args *args) -{ - return B_OK; -} - - -void -arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to) -{ - -} - - -bool -arch_vm_supports_protection(uint32 protection) -{ - return true; -} - - -void -arch_vm_unset_memory_type(struct VMArea *area) -{ - -} - - -status_t -arch_vm_set_memory_type(struct VMArea *area, phys_addr_t physicalBase, - uint32 type) -{ - return B_OK; -} - - status_t arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map) { diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 7502f4d3e4..256aaf72b3 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -43,7 +43,6 @@ if $(TARGET_ARCH) = x86_64 { arch_smp.cpp arch_thread.cpp arch_timer.cpp - arch_vm.cpp arch_vm_translation_map.cpp arch_system_info.cpp arch_user_debugger.cpp @@ -87,6 +86,7 @@ local archGenericSources = arch_cpu.cpp arch_debug_console.cpp arch_int.cpp + arch_vm.cpp pic.cpp ; diff --git a/src/system/kernel/arch/x86/arch_vm.cpp b/src/system/kernel/arch/x86/arch_vm.cpp index 51715ecadd..8fe04923de 100644 --- a/src/system/kernel/arch/x86/arch_vm.cpp +++ b/src/system/kernel/arch/x86/arch_vm.cpp @@ -656,7 +656,12 @@ arch_vm_init_post_area(kernel_args *args) return B_NO_MEMORY; } + // TODO x86_64 +#ifndef __x86_64__ return bios_init(); +#else + return B_OK; +#endif } From 950b24e32d8ddbc0d2a4e46de77c0fb4cc18b128 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 17:02:58 +0100 Subject: [PATCH 064/273] Begun work on VMTranslationMap implementation for x86_64. * Added empty source files for all the 64-bit paging method code, and a stub implementation of X86PagingMethod64Bit. * arch_vm_translation_map.cpp has been modified to use X86PagingMethod64Bit on x86_64. --- headers/private/kernel/arch/x86/arch_kernel.h | 18 ++-- src/system/kernel/arch/x86/64/int.cpp | 1 - src/system/kernel/arch/x86/64/stubs.cpp | 45 ---------- src/system/kernel/arch/x86/Jamfile | 25 ++++-- .../arch/x86/arch_vm_translation_map.cpp | 16 +++- .../x86/paging/64bit/X86PagingMethod64Bit.cpp | 82 +++++++++++++++++++ .../x86/paging/64bit/X86PagingMethod64Bit.h | 47 +++++++++++ .../paging/64bit/X86PagingStructures64Bit.cpp | 17 ++++ .../paging/64bit/X86PagingStructures64Bit.h | 16 ++++ .../paging/64bit/X86VMTranslationMap64Bit.cpp | 20 +++++ .../paging/64bit/X86VMTranslationMap64Bit.h | 15 ++++ .../kernel/arch/x86/paging/64bit/paging.h | 12 +++ .../x86/paging/x86_physical_page_mapper.h | 1 - .../x86_physical_page_mapper_mapped.cpp | 29 +++++++ .../paging/x86_physical_page_mapper_mapped.h | 24 ++++++ 15 files changed, 304 insertions(+), 64 deletions(-) create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp create mode 100644 src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h create mode 100644 src/system/kernel/arch/x86/paging/64bit/paging.h create mode 100644 src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp create mode 100644 src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.h diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index a30eb94656..14413f9083 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -36,6 +36,10 @@ #define KERNEL_SIZE 0x8000000000 #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) +// Kernel physical memory map area. +#define KERNEL_PMAP_BASE 0xffffff0000000000 +#define KERNEL_PMAP_SIZE 0x8000000000 + // Userspace address space layout. #define USER_BASE 0x0 #define USER_BASE_ANY 0x100000 @@ -51,9 +55,9 @@ // memory layout -#define KERNEL_BASE 0x80000000 -#define KERNEL_SIZE 0x80000000 -#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) +#define KERNEL_BASE 0x80000000 +#define KERNEL_SIZE 0x80000000 +#define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) /* User space layout is a little special: * The user space does not completely cover the space not covered by the @@ -65,10 +69,10 @@ * TODO: introduce the 1Mb lower barrier again - it's only used for vm86 mode, * and this should be moved into the kernel (and address space) completely. */ -#define USER_BASE 0x00 -#define USER_BASE_ANY 0x100000 -#define USER_SIZE (KERNEL_BASE - 0x10000) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_BASE 0x00 +#define USER_BASE_ANY 0x100000 +#define USER_SIZE (KERNEL_BASE - 0x10000) +#define USER_TOP (USER_BASE + USER_SIZE) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index 04671a5dd2..849777b96c 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -178,7 +178,6 @@ arch_int_init(kernel_args* args) // Set up the legacy PIC. pic_init(); - panic("not implemented\n"); return B_OK; } diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 348887c54c..1802e922e2 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -479,51 +479,6 @@ x86_init_user_debug() } -status_t -arch_vm_translation_map_create_map(bool kernel, VMTranslationMap** _map) -{ - return B_ERROR; -} - - -status_t -arch_vm_translation_map_init(kernel_args *args, - VMPhysicalPageMapper** _physicalPageMapper) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_init_post_sem(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_init_post_area(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_vm_translation_map_early_map(kernel_args *args, addr_t va, phys_addr_t pa, - uint8 attributes, phys_addr_t (*get_free_page)(kernel_args *)) -{ - return B_ERROR; -} - - -bool -arch_vm_translation_map_is_kernel_page_accessible(addr_t virtualAddress, - uint32 protection) -{ - return true; -} - - // Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. status_t diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 256aaf72b3..a67e4204f3 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -11,13 +11,12 @@ UsePrivateKernelHeaders ; UsePrivateHeaders shared ; SEARCH_SOURCE += [ FDirName $(SUBDIR) paging ] ; -SEARCH_SOURCE += [ FDirName $(SUBDIR) paging 32bit ] ; -SEARCH_SOURCE += [ FDirName $(SUBDIR) paging pae ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) timers ] ; local archSpecificSources ; if $(TARGET_ARCH) = x86_64 { SEARCH_SOURCE += [ FDirName $(SUBDIR) 64 ] ; + SEARCH_SOURCE += [ FDirName $(SUBDIR) paging 64bit ] ; archSpecificSources = arch.S @@ -25,9 +24,19 @@ if $(TARGET_ARCH) = x86_64 { int.cpp interrupts.S stubs.cpp + + # paging + #x86_physical_page_mapper_mapped.cpp + + # paging/64bit + X86PagingMethod64Bit.cpp + X86PagingStructures64Bit.cpp + X86VMTranslationMap64Bit.cpp ; } else { SEARCH_SOURCE += [ FDirName $(SUBDIR) 32 ] ; + SEARCH_SOURCE += [ FDirName $(SUBDIR) paging 32bit ] ; + SEARCH_SOURCE += [ FDirName $(SUBDIR) paging pae ] ; archSpecificSources = arch.S @@ -43,7 +52,6 @@ if $(TARGET_ARCH) = x86_64 { arch_smp.cpp arch_thread.cpp arch_timer.cpp - arch_vm_translation_map.cpp arch_system_info.cpp arch_user_debugger.cpp apic.cpp @@ -59,11 +67,7 @@ if $(TARGET_ARCH) = x86_64 { x86_syscalls.cpp # paging - x86_physical_page_mapper.cpp x86_physical_page_mapper_large_memory.cpp - X86PagingMethod.cpp - X86PagingStructures.cpp - X86VMTranslationMap.cpp # paging/32bit X86PagingMethod32Bit.cpp @@ -87,7 +91,14 @@ local archGenericSources = arch_debug_console.cpp arch_int.cpp arch_vm.cpp + arch_vm_translation_map.cpp pic.cpp + + # paging + x86_physical_page_mapper.cpp + X86PagingMethod.cpp + X86PagingStructures.cpp + X86VMTranslationMap.cpp ; KernelMergeObject kernel_arch_x86.o : diff --git a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp index af3d64b248..836262365e 100644 --- a/src/system/kernel/arch/x86/arch_vm_translation_map.cpp +++ b/src/system/kernel/arch/x86/arch_vm_translation_map.cpp @@ -12,8 +12,12 @@ #include -#include "paging/32bit/X86PagingMethod32Bit.h" -#include "paging/pae/X86PagingMethodPAE.h" +#ifdef __x86_64__ +# include "paging/64bit/X86PagingMethod64Bit.h" +#else +# include "paging/32bit/X86PagingMethod32Bit.h" +# include "paging/pae/X86PagingMethodPAE.h" +#endif //#define TRACE_VM_TMAP @@ -26,10 +30,14 @@ static union { uint64 align; +#ifdef __x86_64__ + char sixty_four[sizeof(X86PagingMethod64Bit)]; +#else char thirty_two[sizeof(X86PagingMethod32Bit)]; #if B_HAIKU_PHYSICAL_BITS == 64 char pae[sizeof(X86PagingMethodPAE)]; #endif +#endif } sPagingMethodBuffer; @@ -74,7 +82,9 @@ arch_vm_translation_map_init(kernel_args *args, } #endif -#if B_HAIKU_PHYSICAL_BITS == 64 +#ifdef __x86_64__ + gX86PagingMethod = new(&sPagingMethodBuffer) X86PagingMethod64Bit; +#elif B_HAIKU_PHYSICAL_BITS == 64 bool paeAvailable = x86_check_feature(IA32_FEATURE_PAE, FEATURE_COMMON); bool paeNeeded = false; for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) { diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp new file mode 100644 index 0000000000..88869ed60d --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp @@ -0,0 +1,82 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "paging/64bit/X86PagingMethod64Bit.h" + +#include +#include + +#include +#include +#include +#include +#include + +//#include "paging/64bit/X86PagingStructures64Bit.h" +//#include "paging/64bit/X86VMTranslationMap64Bit.h" +#include "paging/x86_physical_page_mapper.h" +#include "paging/x86_physical_page_mapper_mapped.h" + + +#define TRACE_X86_PAGING_METHOD_64BIT +#ifdef TRACE_X86_PAGING_METHOD_64BIT +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +// #pragma mark - X86PagingMethod64Bit + + +X86PagingMethod64Bit::X86PagingMethod64Bit() +{ +} + + +X86PagingMethod64Bit::~X86PagingMethod64Bit() +{ +} + + +status_t +X86PagingMethod64Bit::Init(kernel_args* args, + VMPhysicalPageMapper** _physicalPageMapper) +{ + return B_ERROR; +} + + +status_t +X86PagingMethod64Bit::InitPostArea(kernel_args* args) +{ + return B_ERROR; +} + + +status_t +X86PagingMethod64Bit::CreateTranslationMap(bool kernel, VMTranslationMap** _map) +{ + return B_ERROR; +} + + +status_t +X86PagingMethod64Bit::MapEarly(kernel_args* args, addr_t virtualAddress, + phys_addr_t physicalAddress, uint8 attributes, + phys_addr_t (*get_free_page)(kernel_args*)) +{ + return B_ERROR; +} + + +bool +X86PagingMethod64Bit::IsKernelPageAccessible(addr_t virtualAddress, + uint32 protection) +{ + return true; +} + diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h new file mode 100644 index 0000000000..660a0b671f --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h @@ -0,0 +1,47 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_METHOD_64BIT_H +#define KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_METHOD_64BIT_H + + +#include + +#include +#include + +#include "paging/64bit/paging.h" +#include "paging/X86PagingMethod.h" +#include "paging/X86PagingStructures.h" + + +class TranslationMapPhysicalPageMapper; +class X86PhysicalPageMapper; + + +class X86PagingMethod64Bit : public X86PagingMethod { +public: + X86PagingMethod64Bit(); + virtual ~X86PagingMethod64Bit(); + + virtual status_t Init(kernel_args* args, + VMPhysicalPageMapper** _physicalPageMapper); + virtual status_t InitPostArea(kernel_args* args); + + virtual status_t CreateTranslationMap(bool kernel, + VMTranslationMap** _map); + + virtual status_t MapEarly(kernel_args* args, + addr_t virtualAddress, + phys_addr_t physicalAddress, + uint8 attributes, + phys_addr_t (*get_free_page)(kernel_args*)); + + virtual bool IsKernelPageAccessible(addr_t virtualAddress, + uint32 protection); + +}; + + +#endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_METHOD_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp new file mode 100644 index 0000000000..24ff03a971 --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp @@ -0,0 +1,17 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "paging/64bit/X86PagingStructures64Bit.h" + +#include +#include + +#include + +#include + +#include "paging/64bit/X86PagingMethod64Bit.h" + diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h new file mode 100644 index 0000000000..f826c9538f --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h @@ -0,0 +1,16 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_STRUCTURES_64BIT_H +#define KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_STRUCTURES_64BIT_H + + +#include "paging/pae/paging.h" +#include "paging/X86PagingStructures.h" + + + + + +#endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_STRUCTURES_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp new file mode 100644 index 0000000000..090923f23f --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -0,0 +1,20 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "paging/64bit/X86VMTranslationMap64Bit.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "paging/64bit/X86PagingMethod64Bit.h" +#include "paging/64bit/X86PagingStructures64Bit.h" +#include "paging/x86_physical_page_mapper.h" + diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h new file mode 100644 index 0000000000..2e0c000575 --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h @@ -0,0 +1,15 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_ARCH_X86_PAGING_64BIT_X86_VM_TRANSLATION_MAP_64BIT_H +#define KERNEL_ARCH_X86_PAGING_64BIT_X86_VM_TRANSLATION_MAP_64BIT_H + + +#include "paging/X86VMTranslationMap.h" + + + + + +#endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_VM_TRANSLATION_MAP_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/paging.h b/src/system/kernel/arch/x86/paging/64bit/paging.h new file mode 100644 index 0000000000..d0f077cf01 --- /dev/null +++ b/src/system/kernel/arch/x86/paging/64bit/paging.h @@ -0,0 +1,12 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_ARCH_X86_PAGING_PAE_PAGING_H +#define KERNEL_ARCH_X86_PAGING_PAE_PAGING_H + + +#include + + +#endif // KERNEL_ARCH_X86_PAGING_PAE_PAGING_H diff --git a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper.h b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper.h index 31e4796066..a29459b9f0 100644 --- a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper.h +++ b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper.h @@ -10,7 +10,6 @@ struct kernel_args; -struct vm_translation_map_ops; class TranslationMapPhysicalPageMapper { diff --git a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp new file mode 100644 index 0000000000..45f270c10b --- /dev/null +++ b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +/*! Physical page mapper implementation for use where the whole of physical + memory is permanently mapped into the kernel address space. + + This is used on x86_64 where the virtual address space is likely a great + deal larger than the amount of physical memory in the machine, so it can + all be mapped in permanently, which is faster and makes life much easier. +*/ + + +#include "paging/x86_physical_page_mapper_mapped.h" + +#include + +#include +#include +#include +#include +#include + +#include "paging/x86_physical_page_mapper.h" +#include "paging/X86PagingStructures.h" +#include "paging/X86VMTranslationMap.h" + diff --git a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.h b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.h new file mode 100644 index 0000000000..d0c4390729 --- /dev/null +++ b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.h @@ -0,0 +1,24 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ +#ifndef KERNEL_ARCH_X86_PAGING_X86_PHYSICAL_PAGE_MAPPER_MAPPED_H +#define KERNEL_ARCH_X86_PAGING_X86_PHYSICAL_PAGE_MAPPER_MAPPED_H + + +#include + +#include + + +class TranslationMapPhysicalPageMapper; +class X86PhysicalPageMapper; +struct kernel_args; + + +status_t mapped_physical_page_ops_init(kernel_args* args, + X86PhysicalPageMapper*& _pageMapper, + TranslationMapPhysicalPageMapper*& _kernelPageMapper); + + +#endif // KERNEL_ARCH_X86_PAGING_X86_PHYSICAL_PAGE_MAPPER_MAPPED_H From e70dd7e0af671e37378d68c241a081ebeaf8f659 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 18:28:50 +0100 Subject: [PATCH 065/273] Map all physical memory in the long mode paging setup. Since x86_64 has such a large virtual address space all available physical memory can be mapped in to it. The physical page mapper implementation for x86_64 will use this mapping. Also changed the mapping code to map kernel pages with the global flag. --- src/system/boot/platform/bios_ia32/long.cpp | 68 ++++++++++++++++----- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 567c5f34fc..43230becc7 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -6,6 +6,8 @@ #include "long.h" +#include + #include // Include the x86_64 version of descriptors.h @@ -24,6 +26,12 @@ #include "mmu.h" +static const uint64 kTableMappingFlags = 0x3; +static const uint64 kLargePageMappingFlags = 0x183; +static const uint64 kPageMappingFlags = 0x103; + // Global, R/W, Present + + /*! Convert a 32-bit address to a 64-bit address. */ static inline uint64 fix_address(uint64 address) @@ -87,36 +95,68 @@ long_idt_init() static void long_mmu_init() { + uint64* pml4; + uint64* pdpt; + uint64* pageDir; + uint64* pageTable; addr_t physicalAddress; // Allocate the top level PML4. - uint64* pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir); + pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir); memset(pml4, 0, B_PAGE_SIZE); gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4; - // Identity map the first 1GB of memory, do so using large pages. + // Find the highest physical memory address. We map all physical memory + // into the kernel address space, so we want to make sure we map everything + // we have available. + uint64 maxAddress = 0; + for (uint32 i = 0; i < gKernelArgs.num_physical_memory_ranges; i++) { + maxAddress = std::max(maxAddress, + gKernelArgs.physical_memory_range[i].start + + gKernelArgs.physical_memory_range[i].size); + } - uint64* pdpt = (uint64*)mmu_allocate_page(&physicalAddress); + // Want to map at least 4GB, there may be stuff other than usable RAM that + // could be in the first 4GB of physical address space. + maxAddress = std::max(maxAddress, (uint64)0x100000000ll); + maxAddress = ROUNDUP(maxAddress, 0x40000000); + + // Currently only use 1 PDPT (512GB). This will need to change if someone + // wants to use Haiku on a box with more than 512GB of RAM but that's + // probably not going to happen any time soon. + if (maxAddress / 0x40000000 > 512) + panic("Can't currently support more than 512GB of RAM!"); + + // Create page tables for the physical map area. Also map this PDPT + // temporarily at the bottom of the address space so that we are identity + // mapped. + + pdpt = (uint64*)mmu_allocate_page(&physicalAddress); memset(pdpt, 0, B_PAGE_SIZE); - pml4[0] = physicalAddress | 0x3; + pml4[510] = physicalAddress | kTableMappingFlags; + pml4[0] = physicalAddress | kTableMappingFlags; - uint64* pageDir = (uint64*)mmu_allocate_page(&physicalAddress); - memset(pageDir, 0, B_PAGE_SIZE); - pdpt[0] = physicalAddress | 0x3; + for (uint64 i = 0; i < maxAddress; i += 0x40000000) { + dprintf("mapping %llu GB\n", i / 0x40000000); - for (uint32 i = 0; i < 512; i++) { - pageDir[i] = (i * 0x200000) | 0x83; + pageDir = (uint64*)mmu_allocate_page(&physicalAddress); + memset(pageDir, 0, B_PAGE_SIZE); + pdpt[i / 0x40000000] = physicalAddress | kTableMappingFlags; + + for (uint64 j = 0; j < 0x40000000; j += 0x200000) { + pageDir[j / 0x200000] = (i + j) | kLargePageMappingFlags; + } } // Allocate tables for the kernel mappings. pdpt = (uint64*)mmu_allocate_page(&physicalAddress); memset(pdpt, 0, B_PAGE_SIZE); - pml4[511] = physicalAddress | 0x3; + pml4[511] = physicalAddress | kTableMappingFlags; pageDir = (uint64*)mmu_allocate_page(&physicalAddress); memset(pageDir, 0, B_PAGE_SIZE); - pdpt[510] = physicalAddress | 0x3; + pdpt[510] = physicalAddress | kTableMappingFlags; // Store the virtual memory usage information. gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT; @@ -125,13 +165,13 @@ long_mmu_init() // We can now allocate page tables and duplicate the mappings across from // the 32-bit address space to them. - uint64* pageTable = NULL; + pageTable = NULL; for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size / B_PAGE_SIZE; i++) { if ((i % 512) == 0) { pageTable = (uint64*)mmu_allocate_page(&physicalAddress); memset(pageTable, 0, B_PAGE_SIZE); - pageDir[i / 512] = physicalAddress | 0x3; + pageDir[i / 512] = physicalAddress | kTableMappingFlags; // Just performed another virtual allocation, account for it. gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE; @@ -142,7 +182,7 @@ long_mmu_init() &physicalAddress)) continue; - pageTable[i % 512] = physicalAddress | 0x3; + pageTable[i % 512] = physicalAddress | kPageMappingFlags; } gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT From a8f85e6e48ec38ad16d9e1289f031e696220367e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 18:33:21 +0100 Subject: [PATCH 066/273] Removed accidently left in debug message. --- src/system/boot/platform/bios_ia32/long.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 43230becc7..60bcdcf744 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -137,8 +137,6 @@ long_mmu_init() pml4[0] = physicalAddress | kTableMappingFlags; for (uint64 i = 0; i < maxAddress; i += 0x40000000) { - dprintf("mapping %llu GB\n", i / 0x40000000); - pageDir = (uint64*)mmu_allocate_page(&physicalAddress); memset(pageDir, 0, B_PAGE_SIZE); pdpt[i / 0x40000000] = physicalAddress | kTableMappingFlags; From 40aeaeb907f5390e3eeb2958aa5d8362652eca22 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 18:39:23 +0100 Subject: [PATCH 067/273] Should enable CR4.PGE while switching to the kernel. --- src/system/boot/platform/bios_ia32/long_asm.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index c14889a8f6..43be6af4cd 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -25,9 +25,9 @@ FUNCTION(long_enter_kernel): andl $~(1 << 31), %eax movl %eax, %cr0 - // Enable PAE. + // Enable PAE and PGE movl %cr4, %eax - orl $(1 << 5), %eax + orl $(1 << 5) | (1 << 7), %eax movl %eax, %cr4 // Point CR3 to the kernel's PML4. From d687d8ac70249aa14a983002e52b643836f76b2d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 4 Jul 2012 19:57:48 +0100 Subject: [PATCH 068/273] Implementation of VMPhysicalPageMapper for x86_64 using the permanent physical memory mapping. --- src/system/kernel/arch/x86/Jamfile | 2 +- .../x86_physical_page_mapper_mapped.cpp | 228 ++++++++++++++++++ 2 files changed, 229 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index a67e4204f3..c45f2d1f12 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -26,7 +26,7 @@ if $(TARGET_ARCH) = x86_64 { stubs.cpp # paging - #x86_physical_page_mapper_mapped.cpp + x86_physical_page_mapper_mapped.cpp # paging/64bit X86PagingMethod64Bit.cpp diff --git a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp index 45f270c10b..d74fb7cd7a 100644 --- a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp +++ b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,3 +28,230 @@ #include "paging/X86PagingStructures.h" #include "paging/X86VMTranslationMap.h" + +// #pragma mark - + + +class MappedTranslationMapPhysicalPageMapper + : public TranslationMapPhysicalPageMapper { +public: + virtual void Delete(); + + virtual void* GetPageTableAt(phys_addr_t physicalAddress); +}; + + +class MappedPhysicalPageMapper : public X86PhysicalPageMapper { +public: + virtual status_t CreateTranslationMapPhysicalPageMapper( + TranslationMapPhysicalPageMapper** _mapper); + + virtual void* InterruptGetPageTableAt( + phys_addr_t physicalAddress); + + virtual status_t GetPage(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle); + virtual status_t PutPage(addr_t virtualAddress, void* handle); + + virtual status_t GetPageCurrentCPU(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle); + virtual status_t PutPageCurrentCPU(addr_t virtualAddress, + void* handle); + + virtual status_t GetPageDebug(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle); + virtual status_t PutPageDebug(addr_t virtualAddress, + void* handle); + + virtual status_t MemsetPhysical(phys_addr_t address, int value, + phys_size_t length); + virtual status_t MemcpyFromPhysical(void* to, phys_addr_t from, + size_t length, bool user); + virtual status_t MemcpyToPhysical(phys_addr_t to, + const void* from, size_t length, bool user); + virtual void MemcpyPhysicalPage(phys_addr_t to, + phys_addr_t from); +}; + + +static MappedPhysicalPageMapper sPhysicalPageMapper; +static MappedTranslationMapPhysicalPageMapper sKernelPageMapper; + + +// #pragma mark - MappedTranslationMapPhysicalPageMapper + + +void +MappedTranslationMapPhysicalPageMapper::Delete() +{ + delete this; +} + + +void* +MappedTranslationMapPhysicalPageMapper::GetPageTableAt( + phys_addr_t physicalAddress) +{ + ASSERT(physicalAddress % B_PAGE_SIZE == 0); + + return (void*)(physicalAddress + KERNEL_PMAP_BASE); +} + + +// #pragma mark - MappedPhysicalPageMapper + + +status_t +MappedPhysicalPageMapper::CreateTranslationMapPhysicalPageMapper( + TranslationMapPhysicalPageMapper** _mapper) +{ + MappedTranslationMapPhysicalPageMapper* mapper + = new(std::nothrow) MappedTranslationMapPhysicalPageMapper; + if (mapper == NULL) + return B_NO_MEMORY; + + *_mapper = mapper; + return B_OK; +} + + +void* +MappedPhysicalPageMapper::InterruptGetPageTableAt( + phys_addr_t physicalAddress) +{ + ASSERT(physicalAddress % B_PAGE_SIZE == 0); + + return (void*)(physicalAddress + KERNEL_PMAP_BASE); +} + + +status_t +MappedPhysicalPageMapper::GetPage(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle) +{ + if (physicalAddress >= KERNEL_PMAP_BASE) + return B_BAD_ADDRESS; + + *virtualAddress = physicalAddress + KERNEL_PMAP_BASE; + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::PutPage(addr_t virtualAddress, void* handle) +{ + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::GetPageCurrentCPU(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle) +{ + if (physicalAddress >= KERNEL_PMAP_BASE) + return B_BAD_ADDRESS; + + *virtualAddress = physicalAddress + KERNEL_PMAP_BASE; + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::PutPageCurrentCPU(addr_t virtualAddress, + void* handle) +{ + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::GetPageDebug(phys_addr_t physicalAddress, + addr_t* virtualAddress, void** handle) +{ + if (physicalAddress >= KERNEL_PMAP_BASE) + return B_BAD_ADDRESS; + + *virtualAddress = physicalAddress + KERNEL_PMAP_BASE; + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::PutPageDebug(addr_t virtualAddress, void* handle) +{ + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::MemsetPhysical(phys_addr_t address, int value, + phys_size_t length) +{ + if (address >= KERNEL_PMAP_SIZE || address + length > KERNEL_PMAP_SIZE) + return B_BAD_ADDRESS; + + memset((void*)(address + KERNEL_PMAP_BASE), value, length); + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::MemcpyFromPhysical(void* to, phys_addr_t _from, + size_t length, bool user) +{ + if (_from >= KERNEL_PMAP_SIZE || _from + length > KERNEL_PMAP_SIZE) + return B_BAD_ADDRESS; + + void* from = (void*)(_from + KERNEL_PMAP_BASE); + + if (user) + return user_memcpy(to, from, length); + else + memcpy(to, from, length); + + return B_OK; +} + + +status_t +MappedPhysicalPageMapper::MemcpyToPhysical(phys_addr_t _to, const void* from, + size_t length, bool user) +{ + if (_to >= KERNEL_PMAP_SIZE || _to + length > KERNEL_PMAP_SIZE) + return B_BAD_ADDRESS; + + void* to = (void*)(_to + KERNEL_PMAP_BASE); + + if (user) + return user_memcpy(to, from, length); + else + memcpy(to, from, length); + + return B_OK; +} + + +void +MappedPhysicalPageMapper::MemcpyPhysicalPage(phys_addr_t to, + phys_addr_t from) +{ + memcpy((void*)(to + KERNEL_PMAP_BASE), (void*)(from + KERNEL_PMAP_BASE), + B_PAGE_SIZE); +} + + +// #pragma mark - Initialization + + +status_t +mapped_physical_page_ops_init(kernel_args* args, + X86PhysicalPageMapper*& _pageMapper, + TranslationMapPhysicalPageMapper*& _kernelPageMapper) +{ + new(&sPhysicalPageMapper) MappedPhysicalPageMapper; + new(&sKernelPageMapper) MappedTranslationMapPhysicalPageMapper; + + _pageMapper = &sPhysicalPageMapper; + _kernelPageMapper = &sKernelPageMapper; + return B_OK; +} From 78d482e3b8a7b67ed37a7479fddeb735897f282d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 09:10:50 +0100 Subject: [PATCH 069/273] Style fixes. --- headers/os/kernel/OS.h | 2 +- .../kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index c3fe2b0261..633e4541b5 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -645,7 +645,7 @@ typedef enum cpu_types { #define B_CPU_x86_VENDOR_MASK 0xff00 -#if defined(__INTEL__) || defined(__x86_64) +#if defined(__INTEL__) || defined(__x86_64__) typedef union { struct { uint32 max_eax; diff --git a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp index d74fb7cd7a..babdbb87c6 100644 --- a/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp +++ b/src/system/kernel/arch/x86/paging/x86_physical_page_mapper_mapped.cpp @@ -224,9 +224,8 @@ MappedPhysicalPageMapper::MemcpyToPhysical(phys_addr_t _to, const void* from, if (user) return user_memcpy(to, from, length); - else - memcpy(to, from, length); + memcpy(to, from, length); return B_OK; } From 2f36ef5afe5aae9b150597d6281826a1c3ed2f3a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 13:52:36 +0100 Subject: [PATCH 070/273] Fixed the x86_64 setjmp implementation. * typedef for jmp_buf was using int where it should be long. * setjmp was clearing the buffer pointer rather than the signal mask before calling sigsetjmp. * KDL now works without crashing on x86_64. --- headers/posix/arch/x86_64/arch_setjmp.h | 2 +- src/system/libroot/posix/arch/x86_64/sigsetjmp.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/headers/posix/arch/x86_64/arch_setjmp.h b/headers/posix/arch/x86_64/arch_setjmp.h index 2d8f39ec4d..e1043da0c3 100644 --- a/headers/posix/arch/x86_64/arch_setjmp.h +++ b/headers/posix/arch/x86_64/arch_setjmp.h @@ -6,6 +6,6 @@ #define _ARCH_SETJMP_H_ -typedef int __jmp_buf[8]; +typedef unsigned long __jmp_buf[8]; #endif /* _ARCH_SETJMP_H_ */ diff --git a/src/system/libroot/posix/arch/x86_64/sigsetjmp.S b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S index 25bef80a68..0e7b5afc77 100644 --- a/src/system/libroot/posix/arch/x86_64/sigsetjmp.S +++ b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S @@ -31,7 +31,7 @@ FUNCTION_END(setjmp) /* int setjmp(jmp_buf buffer) */ FUNCTION(setjmp): // Jump to sigsetjmp with a zero saveMask. - xorl %edi, %edi + xorl %esi, %esi jmp sigsetjmp FUNCTION_END(setjmp) From 0da10c8b51f9ec443a53873b37d07fab30a5734e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 13:55:59 +0100 Subject: [PATCH 071/273] Some fixes to the long mode switch code. * Wasn't storing the fixed virtual address of the PML4 in kernel_args. * After switching to long mode, reload GDTR with the virtual address of the GDT. This was working fine until now because the physical address was identity mapped, but broke as soon as I removed the identity mapping. --- src/system/boot/platform/bios_ia32/long.cpp | 13 +++---- src/system/boot/platform/bios_ia32/long.h | 5 +-- src/system/boot/platform/bios_ia32/long_asm.S | 34 +++++++++++++++---- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 60bcdcf744..2a942df653 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -104,7 +104,7 @@ long_mmu_init() // Allocate the top level PML4. pml4 = (uint64*)mmu_allocate_page(&gKernelArgs.arch_args.phys_pgdir); memset(pml4, 0, B_PAGE_SIZE); - gKernelArgs.arch_args.vir_pgdir = (uint64)(addr_t)pml4; + gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pml4); // Find the highest physical memory address. We map all physical memory // into the kernel address space, so we want to make sure we map everything @@ -319,14 +319,11 @@ long_start_kernel() // We're about to enter the kernel -- disable console output. stdout = NULL; - // Load the new GDT. The physical address is used because long_enter_kernel - // disables 32-bit paging. - gdt_idt_descr gdtr = { GDT_LIMIT - 1, gKernelArgs.arch_args.phys_gdt }; - asm volatile("lgdt %0" :: "m"(gdtr)); - // Enter the kernel! - long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, entry, stackTop, - kernelArgs, 0); + long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, + gKernelArgs.arch_args.phys_gdt, gKernelArgs.arch_args.vir_gdt, + entry, stackTop, kernelArgs, 0); + panic("Shouldn't get here"); } diff --git a/src/system/boot/platform/bios_ia32/long.h b/src/system/boot/platform/bios_ia32/long.h index de2a0392c7..084b5b36e8 100644 --- a/src/system/boot/platform/bios_ia32/long.h +++ b/src/system/boot/platform/bios_ia32/long.h @@ -9,8 +9,9 @@ #include -extern "C" void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, - uint64 kernelArgs, int currentCPU); +extern "C" void long_enter_kernel(uint32 physPML4, uint32 physGDT, + uint64 virtGDT, uint64 entry, uint64 stackTop, uint64 kernelArgs, + int currentCPU); extern void long_start_kernel(); diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 43be6af4cd..30bfd2be02 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -11,13 +11,22 @@ #undef __x86_64__ +#define GDT_LIMIT 0x800 + + .code32 -/*! void long_enter_kernel(uint32 pml4, uint64 entry, uint64 stackTop, - uint64 kernelArgs, int currentCPU); +/*! void long_enter_kernel(uint32 physPML4, uint32 physGDT, uint64 virtGDT, + uint64 entry, uint64 stackTop, uint64 kernelArgs, int currentCPU); */ FUNCTION(long_enter_kernel): + // We're about to disable paging, so we need to load the the physical + // address of our GDT. + movl 8(%esp), %eax + movl %eax, (long_gdtr + 2) + lgdtl (long_gdtr) + // Currently running with 32-bit paging tables at an identity mapped // address. To switch to 64-bit paging we must first disable 32-bit paging, // otherwise loading the new CR3 will fault. @@ -62,11 +71,16 @@ FUNCTION(long_enter_kernel): // Clear the high 32 bits of RSP. movl %esp, %esp + // Load the virtual address of the GDT. + movq 12(%rsp), %rax + movq %rax, long_gdtr + 2(%rip) + lgdtq long_gdtr(%rip) + // Get the entry point address, arguments and new stack pointer. - movq 8(%rsp), %rax - movq 24(%rsp), %rdi - movl 32(%rsp), %esi - movq 16(%rsp), %rsp + movq 20(%rsp), %rax + movq 36(%rsp), %rdi + movl 44(%rsp), %esi + movq 28(%rsp), %rsp // Clear the stack frame/RFLAGS. xorq %rbp, %rbp @@ -75,3 +89,11 @@ FUNCTION(long_enter_kernel): // Call the kernel entry point. call *%rax + + +.data + + +long_gdtr: + .word GDT_LIMIT - 1 + .quad 0 From 898b29e3628ba9252c527e6296b88cf71d37b863 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 15:35:43 +0100 Subject: [PATCH 072/273] Added temporary stack trace function to x86_64. Will be merged with the x86 one later on. Requires -fno-omit-frame-pointer on the kernel build flags, GCC defaults to not generating stack frames on x86_64. --- build/jam/BuildSetup | 6 ++++-- src/system/kernel/arch/x86/64/arch.S | 7 +++++++ src/system/kernel/arch/x86/64/stubs.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 1e924f0d75..d0897176ab 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -391,8 +391,10 @@ switch $(HAIKU_ARCH) { # Kernel lives in the top 2GB of the address space, use kernel code # model. Also disable the red zone, which cannot be used in kernel # code due to interrupts. - HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel -mno-red-zone ; - HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel -mno-red-zone ; + HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel -mno-red-zone + -fno-omit-frame-pointer ; + HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel -mno-red-zone + -fno-omit-frame-pointer ; HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ; # Bootloader is 32-bit. diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index fcf7d26916..eb51f75691 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -32,6 +32,13 @@ FUNCTION(x86_fxsave_swap): FUNCTION_END(x86_fxsave_swap) +/* addr_t x86_read_ebp(); */ +FUNCTION(x86_read_ebp): + mov %rbp, %rax + ret +FUNCTION_END(x86_read_ebp) + + /* uint64 x86_read_msr(uint32 register); */ FUNCTION(x86_read_msr): mov %edi, %ecx diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 1802e922e2..fc77e25637 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -85,10 +85,32 @@ arch_debug_save_registers(struct arch_debug_registers* registers) } +struct stack_frame { + struct stack_frame *previous; + addr_t return_address; +}; + + void arch_debug_stack_trace(void) { + addr_t rbp = x86_read_ebp(); + kprintf("frame caller\n"); + + for (int32 callIndex = 0;; callIndex++) { + if (rbp == 0) + break; + + stack_frame* frame = (stack_frame*)rbp; + if (frame->return_address == 0) + break; + + kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, + (addr_t)frame->previous - rbp, frame->return_address); + + rbp = (addr_t)frame->previous; + } } @@ -168,6 +190,8 @@ arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, void (*function)(void*), void* parameter) { // To be implemented in asm, not here. + + function(parameter); } From 1671cfdf2c488cd9265ccb76a3b8ee3a393b0d9e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 16:11:11 +0100 Subject: [PATCH 073/273] Improved stack tracer, traces over iframes. --- src/system/kernel/arch/x86/64/stubs.cpp | 58 ++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index fc77e25637..6e904b0f56 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -91,6 +91,41 @@ struct stack_frame { }; +static bool +is_iframe(addr_t frame) +{ + addr_t previousFrame = *(addr_t*)frame; + return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0); +} + + +static void +print_iframe(struct iframe* frame) +{ + bool isUser = IFRAME_IS_USER(frame); + + kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, + isUser ? (uint64*)(frame + 1) : &frame->user_rsp); + + kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%-16lx rdx 0x%lx\n", + frame->rax, frame->rbx, frame->rcx, frame->rdx); + kprintf(" rsi 0x%-16lx rdi 0x%-16lx rbp 0x%-16lx r8 0x%lx\n", + frame->rsi, frame->rdi, frame->rbp, frame->r8); + kprintf(" r9 0x%-16lx r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", + frame->r9, frame->r10, frame->r11, frame->r12); + kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%-16lx\n", + frame->r13, frame->r14, frame->r15); + kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->rip, frame->flags); + if (isUser) { + // from user space + kprintf("user rsp 0x%lx", frame->user_rsp); + } + kprintf("\n"); + kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, + frame->error_code); +} + + void arch_debug_stack_trace(void) { @@ -102,14 +137,25 @@ arch_debug_stack_trace(void) if (rbp == 0) break; - stack_frame* frame = (stack_frame*)rbp; - if (frame->return_address == 0) - break; + if (is_iframe(rbp)) { + struct iframe* frame = (struct iframe*)rbp; + print_iframe(frame); + kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, + frame->rbp - rbp, frame->rip); - kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, - (addr_t)frame->previous - rbp, frame->return_address); + rbp = frame->rbp; + } else { + stack_frame* frame = (stack_frame*)rbp; + if (frame->return_address == 0) + break; - rbp = (addr_t)frame->previous; + kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, + (frame->previous != NULL) + ? (addr_t)frame->previous - rbp : 0, + frame->return_address); + + rbp = (addr_t)frame->previous; + } } } From 11d35d1b9b453cf95392b2ae8fa0941266e85d78 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 5 Jul 2012 20:17:31 +0100 Subject: [PATCH 074/273] Fixed tracing printf formats in VM code. --- src/system/kernel/vm/VMAddressSpace.cpp | 5 +- src/system/kernel/vm/VMAnonymousCache.cpp | 16 +++--- src/system/kernel/vm/VMCache.cpp | 16 +++--- src/system/kernel/vm/VMKernelAddressSpace.cpp | 2 +- src/system/kernel/vm/vm.cpp | 52 ++++++++++--------- src/system/kernel/vm/vm_page.cpp | 24 +++++---- 6 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/system/kernel/vm/VMAddressSpace.cpp b/src/system/kernel/vm/VMAddressSpace.cpp index 7763149ecd..c42e692473 100644 --- a/src/system/kernel/vm/VMAddressSpace.cpp +++ b/src/system/kernel/vm/VMAddressSpace.cpp @@ -195,8 +195,9 @@ VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel, return status; } - TRACE(("VMAddressSpace::Create(): team %ld (%skernel): %#lx bytes starting at " - "%#lx => %p\n", teamID, kernel ? "" : "!", size, base, addressSpace)); + TRACE(("VMAddressSpace::Create(): team %" B_PRId32 " (%skernel): %#lx " + "bytes starting at %#lx => %p\n", teamID, kernel ? "" : "!", size, + base, addressSpace)); // create the corresponding translation map status = arch_vm_translation_map_create_map(kernel, diff --git a/src/system/kernel/vm/VMAnonymousCache.cpp b/src/system/kernel/vm/VMAnonymousCache.cpp index 28ba8c6e8a..95487bd5ac 100644 --- a/src/system/kernel/vm/VMAnonymousCache.cpp +++ b/src/system/kernel/vm/VMAnonymousCache.cpp @@ -448,8 +448,9 @@ VMAnonymousCache::Init(bool canOvercommit, int32 numPrecommittedPages, int32 numGuardPages, uint32 allocationFlags) { TRACE("%p->VMAnonymousCache::Init(canOvercommit = %s, " - "numPrecommittedPages = %ld, numGuardPages = %ld)\n", this, - canOvercommit ? "yes" : "no", numPrecommittedPages, numGuardPages); + "numPrecommittedPages = %" B_PRId32 ", numGuardPages = %" B_PRId32 + ")\n", this, canOvercommit ? "yes" : "no", numPrecommittedPages, + numGuardPages); status_t error = VMCache::Init(CACHE_TYPE_RAM, allocationFlags); if (error != B_OK) @@ -528,7 +529,7 @@ VMAnonymousCache::Resize(off_t newSize, int priority) status_t VMAnonymousCache::Commit(off_t size, int priority) { - TRACE("%p->VMAnonymousCache::Commit(%lld)\n", this, size); + TRACE("%p->VMAnonymousCache::Commit(%" B_PRIdOFF ")\n", this, size); // If we can overcommit, we don't commit here, but in Fault(). We always // unreserve memory, if we're asked to shrink our commitment, though. @@ -950,8 +951,9 @@ VMAnonymousCache::_SwapBlockGetAddress(off_t pageIndex) status_t VMAnonymousCache::_Commit(off_t size, int priority) { - TRACE("%p->VMAnonymousCache::_Commit(%lld), already committed: %lld " - "(%lld swap)\n", this, size, committed_size, fCommittedSwapSize); + TRACE("%p->VMAnonymousCache::_Commit(%" B_PRIdOFF "), already committed: " + "%" B_PRIdOFF " (%" B_PRIdOFF " swap)\n", this, size, committed_size, + fCommittedSwapSize); // Basic strategy: reserve swap space first, only when running out of swap // space, reserve real memory. @@ -965,8 +967,8 @@ VMAnonymousCache::_Commit(off_t size, int priority) fCommittedSwapSize += swap_space_reserve(size - fCommittedSwapSize); committed_size = fCommittedSwapSize + committedMemory; if (size > fCommittedSwapSize) { - TRACE("%p->VMAnonymousCache::_Commit(%lld), reserved only %lld " - "swap\n", this, size, fCommittedSwapSize); + TRACE("%p->VMAnonymousCache::_Commit(%" B_PRIdOFF "), reserved " + "only %" B_PRIdOFF " swap\n", this, size, fCommittedSwapSize); } } diff --git a/src/system/kernel/vm/VMCache.cpp b/src/system/kernel/vm/VMCache.cpp index c28dcd4406..a174f1d99f 100644 --- a/src/system/kernel/vm/VMCache.cpp +++ b/src/system/kernel/vm/VMCache.cpp @@ -679,7 +679,7 @@ VMCache::Delete() page->SetCacheRef(NULL); TRACE(("vm_cache_release_ref: freeing page 0x%lx\n", - oldPage->physical_page_number)); + page->physical_page_number)); DEBUG_PAGE_ACCESS_START(page); vm_page_free(this, page); } @@ -769,7 +769,7 @@ VMCache::LookupPage(off_t offset) void VMCache::InsertPage(vm_page* page, off_t offset) { - TRACE(("VMCache::InsertPage(): cache %p, page %p, offset %Ld\n", + TRACE(("VMCache::InsertPage(): cache %p, page %p, offset %" B_PRIdOFF "\n", this, page, offset)); AssertLocked(); @@ -928,7 +928,7 @@ VMCache::WaitForPageEvents(vm_page* page, uint32 events, bool relock) void VMCache::AddConsumer(VMCache* consumer) { - TRACE(("add consumer vm cache %p to cache %p\n", consumer, cache)); + TRACE(("add consumer vm cache %p to cache %p\n", consumer, this)); AssertLocked(); consumer->AssertLocked(); @@ -1054,8 +1054,8 @@ VMCache::WriteModified() status_t VMCache::SetMinimalCommitment(off_t commitment, int priority) { - TRACE(("VMCache::SetMinimalCommitment(cache %p, commitment %Ld)\n", - this, commitment)); + TRACE(("VMCache::SetMinimalCommitment(cache %p, commitment %" B_PRIdOFF + ")\n", this, commitment)); AssertLocked(); T(SetMinimalCommitment(this, commitment)); @@ -1088,8 +1088,8 @@ VMCache::SetMinimalCommitment(off_t commitment, int priority) status_t VMCache::Resize(off_t newSize, int priority) { - TRACE(("VMCache::Resize(cache %p, newSize %Ld) old size %Ld\n", - this, newSize, this->virtual_end)); + TRACE(("VMCache::Resize(cache %p, newSize %" B_PRIdOFF ") old size %" + B_PRIdOFF "\n", this, newSize, this->virtual_end)); this->AssertLocked(); T(Resize(this, newSize)); @@ -1400,7 +1400,7 @@ VMCache::_MergeWithOnlyConsumer() { VMCache* consumer = consumers.RemoveHead(); - TRACE(("merge vm cache %p (ref == %ld) with vm cache %p\n", + TRACE(("merge vm cache %p (ref == %" B_PRId32 ") with vm cache %p\n", this, this->fRefCount, consumer)); T(Merge(this, consumer)); diff --git a/src/system/kernel/vm/VMKernelAddressSpace.cpp b/src/system/kernel/vm/VMKernelAddressSpace.cpp index efaa473dc2..9b5c5c20d1 100644 --- a/src/system/kernel/vm/VMKernelAddressSpace.cpp +++ b/src/system/kernel/vm/VMKernelAddressSpace.cpp @@ -151,7 +151,7 @@ VMKernelAddressSpace::CreateArea(const char* name, uint32 wiring, void VMKernelAddressSpace::DeleteArea(VMArea* _area, uint32 allocationFlags) { - TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", area); + TRACE("VMKernelAddressSpace::DeleteArea(%p)\n", _area); VMKernelArea* area = static_cast(_area); object_cache_delete(fAreaObjectCache, area); diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 6cd652cd49..e30c739596 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -60,7 +60,7 @@ //#define TRACE_VM -//#define TRACE_FAULTS +#define TRACE_FAULTS #ifdef TRACE_VM # define TRACE(x) dprintf x #else @@ -784,10 +784,11 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset, uint32 flags, const virtual_address_restrictions* addressRestrictions, bool kernel, VMArea** _area, void** _virtualAddress) { - TRACE(("map_backing_store: aspace %p, cache %p, virtual %p, offset 0x%Lx, " - "size %lu, addressSpec %ld, wiring %d, protection %d, area %p, areaName " - "'%s'\n", addressSpace, cache, addressRestrictions->address, offset, - size, addressRestrictions->address_specification, wiring, protection, + TRACE(("map_backing_store: aspace %p, cache %p, virtual %p, offset 0x%" + B_PRIx64 ", size %" B_PRIuADDR ", addressSpec %" B_PRIu32 ", wiring %d" + ", protection %d, area %p, areaName '%s'\n", addressSpace, cache, + addressRestrictions->address, offset, size, + addressRestrictions->address_specification, wiring, protection, _area, areaName)); cache->AssertLocked(); @@ -1191,7 +1192,8 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size, uint32 pageAllocFlags = (flags & CREATE_AREA_DONT_CLEAR) == 0 ? VM_PAGE_ALLOC_CLEAR : 0; - TRACE(("create_anonymous_area [%ld] %s: size 0x%lx\n", team, name, size)); + TRACE(("create_anonymous_area [%" B_PRId32 "] %s: size 0x%" B_PRIxADDR "\n", + team, name, size)); size = PAGE_ALIGN(size); @@ -1557,10 +1559,10 @@ vm_map_physical_memory(team_id team, const char* name, void** _address, VMCache* cache; addr_t mapOffset; - TRACE(("vm_map_physical_memory(aspace = %ld, \"%s\", virtual = %p, " - "spec = %ld, size = %lu, protection = %ld, phys = %#" B_PRIxPHYSADDR - ")\n", team, name, *_address, addressSpec, size, protection, - physicalAddress)); + TRACE(("vm_map_physical_memory(aspace = %" B_PRId32 ", \"%s\", virtual = %p" + ", spec = %" B_PRIu32 ", size = %" B_PRIxADDR ", protection = %" + B_PRIu32 ", phys = %#" B_PRIxPHYSADDR ")\n", team, name, *_address, + addressSpec, size, protection, physicalAddress)); if (!arch_vm_supports_protection(protection)) return B_NOT_SUPPORTED; @@ -1664,10 +1666,10 @@ vm_map_physical_memory_vecs(team_id team, const char* name, void** _address, uint32 addressSpec, addr_t* _size, uint32 protection, struct generic_io_vec* vecs, uint32 vecCount) { - TRACE(("vm_map_physical_memory_vecs(team = %ld, \"%s\", virtual = %p, " - "spec = %ld, _size = %p, protection = %ld, vecs = %p, " - "vecCount = %ld)\n", team, name, *_address, addressSpec, _size, - protection, vecs, vecCount)); + TRACE(("vm_map_physical_memory_vecs(team = %" B_PRId32 ", \"%s\", virtual " + "= %p, spec = %" B_PRIu32 ", _size = %p, protection = %" B_PRIu32 ", " + "vecs = %p, vecCount = %" B_PRIu32 ")\n", team, name, *_address, + addressSpec, _size, protection, vecs, vecCount)); if (!arch_vm_supports_protection(protection) || (addressSpec & B_MTR_MASK) != 0) { @@ -1859,8 +1861,8 @@ _vm_map_file(team_id team, const char* name, void** _address, // copy of a file at a given time, ie. later changes should not // make it into the mapped copy -- this will need quite some changes // to be done in a nice way - TRACE(("_vm_map_file(fd = %d, offset = %Ld, size = %lu, mapping %ld)\n", - fd, offset, size, mapping)); + TRACE(("_vm_map_file(fd = %d, offset = %" B_PRIdOFF ", size = %lu, mapping " + "%" B_PRIu32 ")\n", fd, offset, size, mapping)); offset = ROUNDDOWN(offset, B_PAGE_SIZE); size = PAGE_ALIGN(size); @@ -2249,7 +2251,8 @@ delete_area(VMAddressSpace* addressSpace, VMArea* area, status_t vm_delete_area(team_id team, area_id id, bool kernel) { - TRACE(("vm_delete_area(team = 0x%lx, area = 0x%lx)\n", team, id)); + TRACE(("vm_delete_area(team = 0x%" B_PRIx32 ", area = 0x%" B_PRIx32 ")\n", + team, id)); // lock the address space and make sure the area isn't wired AddressSpaceWriteLocker locker; @@ -2520,8 +2523,8 @@ static status_t vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection, bool kernel) { - TRACE(("vm_set_area_protection(team = %#lx, area = %#lx, protection = " - "%#lx)\n", team, areaID, newProtection)); + TRACE(("vm_set_area_protection(team = %#" B_PRIx32 ", area = %#" B_PRIx32 + ", protection = %#" B_PRIx32 ")\n", team, areaID, newProtection)); if (!arch_vm_supports_protection(newProtection)) return B_NOT_SUPPORTED; @@ -3405,7 +3408,7 @@ dump_available_memory(int argc, char** argv) void vm_delete_areas(struct VMAddressSpace* addressSpace, bool deletingAddressSpace) { - TRACE(("vm_delete_areas: called on address space 0x%lx\n", + TRACE(("vm_delete_areas: called on address space 0x%" B_PRIx32 "\n", addressSpace->ID())); addressSpace->WriteLock(); @@ -4365,8 +4368,9 @@ static status_t vm_soft_fault(VMAddressSpace* addressSpace, addr_t originalAddress, bool isWrite, bool isUser, vm_page** wirePage, VMAreaWiredRange* wiredRange) { - FTRACE(("vm_soft_fault: thid 0x%lx address 0x%lx, isWrite %d, isUser %d\n", - thread_get_current_thread_id(), originalAddress, isWrite, isUser)); + FTRACE(("vm_soft_fault: thid 0x%" B_PRIx32 " address 0x%" B_PRIxADDR ", " + "isWrite %d, isUser %d\n", thread_get_current_thread_id(), + originalAddress, isWrite, isUser)); PageFaultContext context(addressSpace, isWrite); @@ -5609,8 +5613,8 @@ get_memory_map_etc(team_id team, const void* address, size_t numBytes, addr_t offset = 0; bool interrupts = are_interrupts_enabled(); - TRACE(("get_memory_map_etc(%ld, %p, %lu bytes, %ld entries)\n", team, - address, numBytes, numEntries)); + TRACE(("get_memory_map_etc(%" B_PRId32 ", %p, %lu bytes, %" B_PRIu32 " " + "entries)\n", team, address, numBytes, numEntries)); if (numEntries == 0 || numBytes == 0) return B_BAD_VALUE; diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index 4c135a220a..b1ede7e18a 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -2449,8 +2449,8 @@ page_writer(void* /*unused*/) writtenPages += numPages; if (writtenPages >= 1024) { bigtime_t now = system_time(); - TRACE(("page writer: wrote 1024 pages (total: %llu ms, " - "collect: %llu ms, write: %llu ms)\n", + TRACE(("page writer: wrote 1024 pages (total: %" B_PRIu64 " ms, " + "collect: %" B_PRIu64 " ms, write: %" B_PRIu64 " ms)\n", (now - lastWrittenTime) / 1000, pageCollectionTime / 1000, pageWritingTime / 1000)); lastWrittenTime = now; @@ -2808,9 +2808,10 @@ full_scan_inactive_pages(page_stats& pageStats, int32 despairLevel) queueLocker.Unlock(); time = system_time() - time; - TRACE_DAEMON(" -> inactive scan (%7lld us): scanned: %7lu, " - "moved: %lu -> cached, %lu -> modified, %lu -> active\n", time, - pagesScanned, pagesToCached, pagesToModified, pagesToActive); + TRACE_DAEMON(" -> inactive scan (%7" B_PRId64 " us): scanned: %7" B_PRIu32 + ", moved: %" B_PRIu32 " -> cached, %" B_PRIu32 " -> modified, %" + B_PRIu32 " -> active\n", time, pagesScanned, pagesToCached, + pagesToModified, pagesToActive); // wake up the page writer, if we tossed it some pages if (pagesToModified > 0) @@ -2904,9 +2905,9 @@ full_scan_active_pages(page_stats& pageStats, int32 despairLevel) } time = system_time() - time; - TRACE_DAEMON(" -> active scan (%7lld us): scanned: %7lu, " - "moved: %lu -> inactive, encountered %lu accessed ones\n", time, - pagesScanned, pagesToInactive, pagesAccessed); + TRACE_DAEMON(" -> active scan (%7" B_PRId64 " us): scanned: %7" B_PRIu32 + ", moved: %" B_PRIu32 " -> inactive, encountered %" B_PRIu32 " accessed" + " ones\n", time, pagesScanned, pagesToInactive, pagesAccessed); } @@ -2934,9 +2935,10 @@ page_daemon_idle_scan(page_stats& pageStats) static void page_daemon_full_scan(page_stats& pageStats, int32 despairLevel) { - TRACE_DAEMON("page daemon: full run: free: %lu, cached: %lu, " - "to free: %lu\n", pageStats.totalFreePages, pageStats.cachedPages, - pageStats.unsatisfiedReservations + sFreeOrCachedPagesTarget + TRACE_DAEMON("page daemon: full run: free: %" B_PRIu32 ", cached: %" + B_PRIu32 ", to free: %" B_PRIu32 "\n", pageStats.totalFreePages, + pageStats.cachedPages, pageStats.unsatisfiedReservations + + sFreeOrCachedPagesTarget - (pageStats.totalFreePages + pageStats.cachedPages)); // Walk the inactive list and transfer pages to the cached and modified From e276cc0457a4ddb3f137504e220ee5e839f132d4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 6 Jul 2012 12:52:35 +0100 Subject: [PATCH 075/273] Finished implementation of x86_64 paging. * vm_init now runs up until create_preloaded_image_areas(), which needs fixing to handle ELF64. * Not completely tested. I know Map(), Unmap() and Query() work fine, the other methods have not been tested as the kernel doesn't boot far enough for any of them to be called yet. As far as I know they're correct, though. * Not yet implemented the destructor for X86VMTranslationMap64Bit or Init() for a user address space. --- src/system/kernel/arch/x86/64/stubs.cpp | 19 +- src/system/kernel/arch/x86/arch_cpu.cpp | 6 - .../x86/paging/32bit/X86PagingMethod32Bit.cpp | 2 +- .../x86/paging/32bit/X86PagingMethod32Bit.h | 2 +- .../x86/paging/64bit/X86PagingMethod64Bit.cpp | 263 +++++- .../x86/paging/64bit/X86PagingMethod64Bit.h | 123 ++- .../paging/64bit/X86PagingStructures64Bit.cpp | 32 + .../paging/64bit/X86PagingStructures64Bit.h | 16 +- .../paging/64bit/X86VMTranslationMap64Bit.cpp | 755 +++++++++++++++++- .../paging/64bit/X86VMTranslationMap64Bit.h | 54 ++ .../kernel/arch/x86/paging/64bit/paging.h | 74 +- .../kernel/arch/x86/paging/X86PagingMethod.h | 4 +- .../arch/x86/paging/X86PagingStructures.h | 2 +- .../x86/paging/pae/X86PagingMethodPAE.cpp | 2 +- .../arch/x86/paging/pae/X86PagingMethodPAE.h | 2 +- .../x86/paging/pae/X86VMTranslationMapPAE.cpp | 4 +- 16 files changed, 1325 insertions(+), 35 deletions(-) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 6e904b0f56..fe6b42b829 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -107,15 +107,18 @@ print_iframe(struct iframe* frame) kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, isUser ? (uint64*)(frame + 1) : &frame->user_rsp); - kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%-16lx rdx 0x%lx\n", - frame->rax, frame->rbx, frame->rcx, frame->rdx); - kprintf(" rsi 0x%-16lx rdi 0x%-16lx rbp 0x%-16lx r8 0x%lx\n", - frame->rsi, frame->rdi, frame->rbp, frame->r8); - kprintf(" r9 0x%-16lx r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", - frame->r9, frame->r10, frame->r11, frame->r12); - kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%-16lx\n", - frame->r13, frame->r14, frame->r15); + kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%lx\n", frame->rax, + frame->rbx, frame->rcx); + kprintf(" rdx 0x%-16lx rsi 0x%-16lx rdi 0x%lx\n", frame->rdx, + frame->rsi, frame->rdi); + kprintf(" rbp 0x%-16lx r8 0x%-16lx r9 0x%lx\n", frame->rbp, + frame->r8, frame->r9); + kprintf(" r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", frame->r10, + frame->r11, frame->r12); + kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%lx\n", frame->r13, + frame->r14, frame->r15); kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->rip, frame->flags); + if (isUser) { // from user space kprintf("user rsp 0x%lx", frame->user_rsp); diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index ff0e971da4..a618504d7f 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -853,12 +853,9 @@ arch_cpu_init_post_vm(kernel_args* args) &virtualRestrictions, &physicalRestrictions, (void**)&sDoubleFaultStacks); - // TODO x86_64 -#ifndef __x86_64__ X86PagingStructures* kernelPagingStructures = static_cast( VMAddressSpace::Kernel()->TranslationMap())->PagingStructures(); -#endif // setup task-state segments for (i = 0; i < args->num_cpus; i++) { @@ -877,12 +874,9 @@ arch_cpu_init_post_vm(kernel_args* args) // initialize the double fault tss init_double_fault(i); - // TODO x86_64 -#ifndef __x86_64__ // init active translation map gCPU[i].arch.active_paging_structures = kernelPagingStructures; kernelPagingStructures->AddReference(); -#endif } // set the current hardware task on cpu 0 diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp index ad0c812357..987f3b4c8d 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.cpp @@ -367,7 +367,7 @@ X86PagingMethod32Bit::CreateTranslationMap(bool kernel, VMTranslationMap** _map) status_t X86PagingMethod32Bit::MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)) + page_num_t (*get_free_page)(kernel_args*)) { // XXX horrible back door to map a page quickly regardless of translation // map object, etc. used only during VM setup. diff --git a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.h b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.h index 92951f5b39..f781f7df1f 100644 --- a/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.h +++ b/src/system/kernel/arch/x86/paging/32bit/X86PagingMethod32Bit.h @@ -31,7 +31,7 @@ public: addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)); + page_num_t (*get_free_page)(kernel_args*)); virtual bool IsKernelPageAccessible(addr_t virtualAddress, uint32 protection); diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp index 88869ed60d..4c622548d3 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp @@ -1,6 +1,11 @@ /* * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. */ @@ -15,13 +20,13 @@ #include #include -//#include "paging/64bit/X86PagingStructures64Bit.h" -//#include "paging/64bit/X86VMTranslationMap64Bit.h" +#include "paging/64bit/X86PagingStructures64Bit.h" +#include "paging/64bit/X86VMTranslationMap64Bit.h" #include "paging/x86_physical_page_mapper.h" #include "paging/x86_physical_page_mapper_mapped.h" -#define TRACE_X86_PAGING_METHOD_64BIT +//#define TRACE_X86_PAGING_METHOD_64BIT #ifdef TRACE_X86_PAGING_METHOD_64BIT # define TRACE(x...) dprintf(x) #else @@ -33,6 +38,11 @@ X86PagingMethod64Bit::X86PagingMethod64Bit() + : + fKernelPhysicalPML4(0), + fKernelVirtualPML4(NULL), + fPhysicalPageMapper(NULL), + fKernelPhysicalPageMapper(NULL) { } @@ -46,6 +56,19 @@ status_t X86PagingMethod64Bit::Init(kernel_args* args, VMPhysicalPageMapper** _physicalPageMapper) { + fKernelPhysicalPML4 = args->arch_args.phys_pgdir; + fKernelVirtualPML4 = (uint64*)(addr_t)args->arch_args.vir_pgdir; + + // Ensure that the user half of the address space is clear. This removes + // the temporary identity mapping made by the boot loader. + memset(fKernelVirtualPML4, 0, sizeof(uint64) * 256); + arch_cpu_global_TLB_invalidate(); + + // Create the physical page mapper. + mapped_physical_page_ops_init(args, fPhysicalPageMapper, + fKernelPhysicalPageMapper); + + *_physicalPageMapper = fPhysicalPageMapper; return B_ERROR; } @@ -53,23 +76,107 @@ X86PagingMethod64Bit::Init(kernel_args* args, status_t X86PagingMethod64Bit::InitPostArea(kernel_args* args) { - return B_ERROR; + // Create an area to represent the kernel PML4. + area_id area = create_area("kernel pml4", (void**)&fKernelVirtualPML4, + B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, + B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + if (area < B_OK) + return area; + + return B_OK; } status_t X86PagingMethod64Bit::CreateTranslationMap(bool kernel, VMTranslationMap** _map) { - return B_ERROR; + X86VMTranslationMap64Bit* map = new(std::nothrow) X86VMTranslationMap64Bit; + if (map == NULL) + return B_NO_MEMORY; + + status_t error = map->Init(kernel); + if (error != B_OK) { + delete map; + return error; + } + + *_map = map; + return B_OK; } status_t X86PagingMethod64Bit::MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)) + page_num_t (*get_free_page)(kernel_args*)) { - return B_ERROR; + TRACE("X86PagingMethod64Bit::MapEarly(%#" B_PRIxADDR ", %#" B_PRIxPHYSADDR + ", %#" B_PRIx8 ")\n", virtualAddress, physicalAddress, attributes); + + // Get the PDPT. We should be mapping on an existing PDPT at this stage. + uint64* pml4e = &fKernelVirtualPML4[VADDR_TO_PML4E(virtualAddress)]; + ASSERT((*pml4e & X86_64_PML4E_PRESENT) != 0); + uint64* virtualPDPT = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + *pml4e & X86_64_PML4E_ADDRESS_MASK); + + // Get the page directory. + uint64* pdpte = &virtualPDPT[VADDR_TO_PDPTE(virtualAddress)]; + uint64* virtualPageDir; + if ((*pdpte & X86_64_PDPTE_PRESENT) == 0) { + phys_addr_t physicalPageDir = get_free_page(args) * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::MapEarly(): creating page directory for va" + " %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, + physicalPageDir); + + SetTableEntry(pdpte, (physicalPageDir & X86_64_PDPTE_ADDRESS_MASK) + | X86_64_PDPTE_PRESENT + | X86_64_PDPTE_WRITABLE); + + // Map it and zero it. + virtualPageDir = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + physicalPageDir); + memset(virtualPageDir, 0, B_PAGE_SIZE); + } else { + virtualPageDir = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + *pdpte & X86_64_PDPTE_ADDRESS_MASK); + } + + // Get the page table. + uint64* pde = &virtualPageDir[VADDR_TO_PDE(virtualAddress)]; + uint64* virtualPageTable; + if ((*pde & X86_64_PDE_PRESENT) == 0) { + phys_addr_t physicalPageTable = get_free_page(args) * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::MapEarly(): creating page table for va" + " %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, + physicalPageTable); + + SetTableEntry(pde, (physicalPageTable & X86_64_PDE_ADDRESS_MASK) + | X86_64_PDE_PRESENT + | X86_64_PDE_WRITABLE); + + // Map it and zero it. + virtualPageTable = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + physicalPageTable); + memset(virtualPageTable, 0, B_PAGE_SIZE); + } else { + virtualPageTable = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( + *pde & X86_64_PDE_ADDRESS_MASK); + } + + // The page table entry must not already be mapped. + uint64* pte = &virtualPageTable[VADDR_TO_PTE(virtualAddress)]; + ASSERT_PRINT( + (*pte & X86_64_PTE_PRESENT) == 0, + "virtual address: %#" B_PRIxADDR ", existing pte: %#" B_PRIx64, + virtualAddress, *pte); + + // Fill in the table entry. + PutPageTableEntryInTable(pte, physicalAddress, attributes, 0, + IS_KERNEL_ADDRESS(virtualAddress)); + + return B_OK; } @@ -80,3 +187,145 @@ X86PagingMethod64Bit::IsKernelPageAccessible(addr_t virtualAddress, return true; } + +/*! Traverses down the paging structure hierarchy to find the page table for a + virtual address, allocating new tables if required. +*/ +/*static*/ uint64* +X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, + addr_t virtualAddress, bool isKernel, bool allocateTables, + vm_page_reservation* reservation, + TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) +{ + TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(%#" B_PRIxADDR ", " + "%d)\n", virtualAddress, allocateTables); + + // Get the PDPT. + uint64* pml4e = &virtualPML4[VADDR_TO_PML4E(virtualAddress)]; + if ((*pml4e & X86_64_PML4E_PRESENT) == 0) { + if (!allocateTables) + return NULL; + + // Allocate a new PDPT. + vm_page* page = vm_page_allocate_page(reservation, + PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); + + DEBUG_PAGE_ACCESS_END(page); + + phys_addr_t physicalPDPT + = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating PDPT " + "for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, + physicalPDPT); + + SetTableEntry(pml4e, (physicalPDPT & X86_64_PML4E_ADDRESS_MASK) + | X86_64_PML4E_PRESENT + | X86_64_PML4E_WRITABLE + | (isKernel ? 0 : X86_64_PML4E_USER)); + + mapCount++; + } + + uint64* virtualPDPT = (uint64*)pageMapper->GetPageTableAt( + *pml4e & X86_64_PML4E_ADDRESS_MASK); + + // Get the page directory. + uint64* pdpte = &virtualPDPT[VADDR_TO_PDPTE(virtualAddress)]; + if ((*pdpte & X86_64_PDPTE_PRESENT) == 0) { + if (!allocateTables) + return NULL; + + // Allocate a new page directory. + vm_page* page = vm_page_allocate_page(reservation, + PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); + + DEBUG_PAGE_ACCESS_END(page); + + phys_addr_t physicalPageDir + = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page " + "directory for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", + virtualAddress, physicalPageDir); + + SetTableEntry(pdpte, (physicalPageDir & X86_64_PDPTE_ADDRESS_MASK) + | X86_64_PDPTE_PRESENT + | X86_64_PDPTE_WRITABLE + | (isKernel ? 0 : X86_64_PDPTE_USER)); + + mapCount++; + } + + uint64* virtualPageDir = (uint64*)pageMapper->GetPageTableAt( + *pdpte & X86_64_PDPTE_ADDRESS_MASK); + + // Get the page table. + uint64* pde = &virtualPageDir[VADDR_TO_PDE(virtualAddress)]; + if ((*pde & X86_64_PDE_PRESENT) == 0) { + if (!allocateTables) + return NULL; + + // Allocate a new page table. + vm_page* page = vm_page_allocate_page(reservation, + PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR); + + DEBUG_PAGE_ACCESS_END(page); + + phys_addr_t physicalPageTable + = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; + + TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page " + "table for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", + virtualAddress, physicalPageTable); + + SetTableEntry(pde, (physicalPageTable & X86_64_PDE_ADDRESS_MASK) + | X86_64_PDE_PRESENT + | X86_64_PDE_WRITABLE + | (isKernel ? 0 : X86_64_PDE_USER)); + + mapCount++; + } + + return (uint64*)pageMapper->GetPageTableAt(*pde & X86_64_PDE_ADDRESS_MASK); +} + + +/*static*/ uint64* +X86PagingMethod64Bit::PageTableEntryForAddress(uint64* virtualPML4, + addr_t virtualAddress, bool isKernel, bool allocateTables, + vm_page_reservation* reservation, + TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) +{ + uint64* virtualPageTable = PageTableForAddress(virtualPML4, virtualAddress, + isKernel, allocateTables, reservation, pageMapper, mapCount); + if (virtualPageTable == NULL) + return NULL; + + return &virtualPageTable[VADDR_TO_PTE(virtualAddress)]; +} + + +/*static*/ void +X86PagingMethod64Bit::PutPageTableEntryInTable(uint64* entry, + phys_addr_t physicalAddress, uint32 attributes, uint32 memoryType, + bool globalPage) +{ + uint64 page = (physicalAddress & X86_64_PTE_ADDRESS_MASK) + | X86_64_PTE_PRESENT | (globalPage ? X86_64_PTE_GLOBAL : 0) + | MemoryTypeToPageTableEntryFlags(memoryType); + + // if the page is user accessible, it's automatically + // accessible in kernel space, too (but with the same + // protection) + if ((attributes & B_USER_PROTECTION) != 0) { + page |= X86_64_PTE_USER; + if ((attributes & B_WRITE_AREA) != 0) + page |= X86_64_PTE_WRITABLE; + } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) + page |= X86_64_PTE_WRITABLE; + + // put it in the page table + SetTableEntry(entry, page); +} + diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h index 660a0b671f..130e14ddc0 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.h @@ -1,5 +1,6 @@ /* * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_METHOD_64BIT_H @@ -18,6 +19,7 @@ class TranslationMapPhysicalPageMapper; class X86PhysicalPageMapper; +struct vm_page_reservation; class X86PagingMethod64Bit : public X86PagingMethod { @@ -36,12 +38,131 @@ public: addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)); + page_num_t (*get_free_page)(kernel_args*)); virtual bool IsKernelPageAccessible(addr_t virtualAddress, uint32 protection); + inline X86PhysicalPageMapper* PhysicalPageMapper() const + { return fPhysicalPageMapper; } + inline TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const + { return fKernelPhysicalPageMapper; } + + inline uint64* KernelVirtualPML4() const + { return fKernelVirtualPML4; } + inline phys_addr_t KernelPhysicalPML4() const + { return fKernelPhysicalPML4; } + + static X86PagingMethod64Bit* Method(); + + static uint64* PageTableForAddress(uint64* virtualPML4, + addr_t virtualAddress, bool isKernel, + bool allocateTables, + vm_page_reservation* reservation, + TranslationMapPhysicalPageMapper* + pageMapper, int32& mapCount); + static uint64* PageTableEntryForAddress(uint64* virtualPML4, + addr_t virtualAddress, bool isKernel, + bool allocateTables, + vm_page_reservation* reservation, + TranslationMapPhysicalPageMapper* + pageMapper, int32& mapCount); + + static void PutPageTableEntryInTable( + uint64* entry, phys_addr_t physicalAddress, + uint32 attributes, uint32 memoryType, + bool globalPage); + static uint64 SetTableEntry(uint64* entry, uint64 newEntry); + static uint64 SetTableEntryFlags(uint64* entry, uint64 flags); + static uint64 TestAndSetTableEntry(uint64* entry, + uint64 newEntry, uint64 oldEntry); + static uint64 ClearTableEntry(uint64* entry); + static uint64 ClearTableEntryFlags(uint64* entry, + uint64 flags); + + static uint64 MemoryTypeToPageTableEntryFlags( + uint32 memoryType); + +private: + phys_addr_t fKernelPhysicalPML4; + uint64* fKernelVirtualPML4; + + X86PhysicalPageMapper* fPhysicalPageMapper; + TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper; }; +/*static*/ inline X86PagingMethod64Bit* +X86PagingMethod64Bit::Method() +{ + return static_cast(gX86PagingMethod); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::SetTableEntry(uint64* entry, uint64 newEntry) +{ + return atomic_set64((int64*)entry, newEntry); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::SetTableEntryFlags(uint64* entry, uint64 flags) +{ + return atomic_or64((int64*)entry, flags); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::TestAndSetTableEntry(uint64* entry, uint64 newEntry, + uint64 oldEntry) +{ + return atomic_test_and_set64((int64*)entry, newEntry, oldEntry); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::ClearTableEntry(uint64* entry) +{ + return SetTableEntry(entry, 0); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::ClearTableEntryFlags(uint64* entry, uint64 flags) +{ + return atomic_and64((int64*)entry, ~flags); +} + + +/*static*/ inline uint64 +X86PagingMethod64Bit::MemoryTypeToPageTableEntryFlags(uint32 memoryType) +{ + // ATM we only handle the uncacheable and write-through type explicitly. For + // all other types we rely on the MTRRs to be set up correctly. Since we set + // the default memory type to write-back and since the uncacheable type in + // the PTE overrides any MTRR attribute (though, as per the specs, that is + // not recommended for performance reasons), this reduces the work we + // actually *have* to do with the MTRRs to setting the remaining types + // (usually only write-combining for the frame buffer). + switch (memoryType) { + case B_MTR_UC: + return X86_64_PTE_CACHING_DISABLED | X86_64_PTE_WRITE_THROUGH; + + case B_MTR_WC: + // X86_PTE_WRITE_THROUGH would be closer, but the combination with + // MTRR WC is "implementation defined" for Pentium Pro/II. + return 0; + + case B_MTR_WT: + return X86_64_PTE_WRITE_THROUGH; + + case B_MTR_WP: + case B_MTR_WB: + default: + return 0; + } +} + + #endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_METHOD_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp index 24ff03a971..aeecb239e7 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.cpp @@ -15,3 +15,35 @@ #include "paging/64bit/X86PagingMethod64Bit.h" + +X86PagingStructures64Bit::X86PagingStructures64Bit() + : + fVirtualPML4(NULL) +{ +} + + +X86PagingStructures64Bit::~X86PagingStructures64Bit() +{ + // Free the PML4. + free(fVirtualPML4); +} + + +void +X86PagingStructures64Bit::Init(uint64* virtualPML4, phys_addr_t physicalPML4) +{ + fVirtualPML4 = virtualPML4; + pgdir_phys = physicalPML4; +} + + +void +X86PagingStructures64Bit::Delete() +{ + if (are_interrupts_enabled()) + delete this; + else + deferred_delete(this); +} + diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h index f826c9538f..e3114d25a6 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingStructures64Bit.h @@ -6,11 +6,25 @@ #define KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_STRUCTURES_64BIT_H -#include "paging/pae/paging.h" +#include "paging/64bit/paging.h" #include "paging/X86PagingStructures.h" +struct X86PagingStructures64Bit : X86PagingStructures { + X86PagingStructures64Bit(); + virtual ~X86PagingStructures64Bit(); + void Init(uint64* virtualPML4, + phys_addr_t physicalPML4); + + virtual void Delete(); + + uint64* VirtualPML4() + { return fVirtualPML4; } + +private: + uint64* fVirtualPML4; +}; #endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_PAGING_STRUCTURES_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp index 090923f23f..24e85c2cde 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -1,6 +1,11 @@ /* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk + * Copyright 2008-2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. */ @@ -18,3 +23,751 @@ #include "paging/64bit/X86PagingStructures64Bit.h" #include "paging/x86_physical_page_mapper.h" + +//#define TRACE_X86_VM_TRANSLATION_MAP_64BIT +#ifdef TRACE_X86_VM_TRANSLATION_MAP_64BIT +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +// #pragma mark - X86VMTranslationMap64Bit + + +X86VMTranslationMap64Bit::X86VMTranslationMap64Bit() + : + fPagingStructures(NULL) +{ +} + + +X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit() +{ + TRACE("X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()\n"); + + panic("X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit: TODO"); +} + + +status_t +X86VMTranslationMap64Bit::Init(bool kernel) +{ + TRACE("X86VMTranslationMap64Bit::Init()\n"); + + X86VMTranslationMap::Init(kernel); + + fPagingStructures = new(std::nothrow) X86PagingStructures64Bit; + if (fPagingStructures == NULL) + return B_NO_MEMORY; + + X86PagingMethod64Bit* method = X86PagingMethod64Bit::Method(); + + if (kernel) { + // Get the page mapper. + fPageMapper = method->KernelPhysicalPageMapper(); + + // Kernel PML4 is already mapped. + fPagingStructures->Init(method->KernelVirtualPML4(), + method->KernelPhysicalPML4()); + } else { + panic("X86VMTranslationMap64Bit::Init(): TODO"); + } + + return B_OK; +} + + +size_t +X86VMTranslationMap64Bit::MaxPagesNeededToMap(addr_t start, addr_t end) const +{ + // If start == 0, the actual base address is not yet known to the caller and + // we shall assume the worst case, which is where the start address is the + // last page covered by a PDPT. + if (start == 0) { + start = k64BitPDPTRange - B_PAGE_SIZE; + end += start; + } + + size_t requiredPDPTs = end / k64BitPDPTRange + 1 + - start / k64BitPDPTRange; + size_t requiredPageDirs = end / k64BitPageDirectoryRange + 1 + - start / k64BitPageDirectoryRange; + size_t requiredPageTables = end / k64BitPageTableRange + 1 + - start / k64BitPageTableRange; + + return requiredPDPTs + requiredPageDirs + requiredPageTables; +} + + +status_t +X86VMTranslationMap64Bit::Map(addr_t virtualAddress, phys_addr_t physicalAddress, + uint32 attributes, uint32 memoryType, vm_page_reservation* reservation) +{ + TRACE("X86VMTranslationMap64Bit::Map(%#" B_PRIxADDR ", %#" B_PRIxPHYSADDR + ")\n", virtualAddress, physicalAddress); + + ThreadCPUPinner pinner(thread_get_current_thread()); + + // Look up the page table for the virtual address, allocating new tables + // if required. Shouldn't fail. + uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), virtualAddress, fIsKernelMap, + true, reservation, fPageMapper, fMapCount); + ASSERT(entry != NULL); + + // The entry should not already exist. + ASSERT_PRINT((*entry & X86_64_PTE_PRESENT) == 0, + "virtual address: %#" B_PRIxADDR ", existing pte: %#" B_PRIx64, + virtualAddress, *entry); + + // Fill in the table entry. + X86PagingMethod64Bit::PutPageTableEntryInTable(entry, physicalAddress, + attributes, memoryType, fIsKernelMap); + + // Note: We don't need to invalidate the TLB for this address, as previously + // the entry was not present and the TLB doesn't cache those entries. + + fMapCount++; + + return 0; +} + + +status_t +X86VMTranslationMap64Bit::Unmap(addr_t start, addr_t end) +{ + start = ROUNDDOWN(start, B_PAGE_SIZE); + if (start >= end) + return B_OK; + + TRACE("X86VMTranslationMap64Bit::Unmap(%#" B_PRIxADDR ", %#" B_PRIxADDR + ")\n", start, end); + + ThreadCPUPinner pinner(thread_get_current_thread()); + + do { + uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( + fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + NULL, fPageMapper, fMapCount); + if (pageTable == NULL) { + // Move on to the next page table. + start = ROUNDUP(start + 1, k64BitPageTableRange); + continue; + } + + for (uint32 index = start / B_PAGE_SIZE % k64BitTableEntryCount; + index < k64BitTableEntryCount && start < end; + index++, start += B_PAGE_SIZE) { + if ((pageTable[index] & X86_64_PTE_PRESENT) == 0) + continue; + + TRACE("X86VMTranslationMap64Bit::Unmap(): removing page %#" + B_PRIxADDR " (%#" B_PRIxPHYSADDR ")\n", start, + pageTable[index] & X86_64_PTE_ADDRESS_MASK); + + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags( + &pageTable[index], X86_64_PTE_PRESENT); + fMapCount--; + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flags was set, since only then the entry could have + // been in any TLB. + InvalidatePage(start); + } + } + } while (start != 0 && start < end); + + return B_OK; +} + + +status_t +X86VMTranslationMap64Bit::DebugMarkRangePresent(addr_t start, addr_t end, + bool markPresent) +{ + start = ROUNDDOWN(start, B_PAGE_SIZE); + if (start >= end) + return B_OK; + + TRACE("X86VMTranslationMap64Bit::DebugMarkRangePresent(%#" B_PRIxADDR + ", %#" B_PRIxADDR ")\n", start, end); + + ThreadCPUPinner pinner(thread_get_current_thread()); + + do { + uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( + fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + NULL, fPageMapper, fMapCount); + if (pageTable == NULL) { + // Move on to the next page table. + start = ROUNDUP(start + 1, k64BitPageTableRange); + continue; + } + + for (uint32 index = start / B_PAGE_SIZE % k64BitTableEntryCount; + index < k64BitTableEntryCount && start < end; + index++, start += B_PAGE_SIZE) { + if ((pageTable[index] & X86_64_PTE_PRESENT) == 0) { + if (!markPresent) + continue; + + X86PagingMethod64Bit::SetTableEntryFlags(&pageTable[index], + X86_64_PTE_PRESENT); + } else { + if (markPresent) + continue; + + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags( + &pageTable[index], X86_64_PTE_PRESENT); + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flags was set, since only then the entry could + // have been in any TLB. + InvalidatePage(start); + } + } + } + } while (start != 0 && start < end); + + return B_OK; +} + + +status_t +X86VMTranslationMap64Bit::UnmapPage(VMArea* area, addr_t address, + bool updatePageQueue) +{ + ASSERT(address % B_PAGE_SIZE == 0); + + TRACE("X86VMTranslationMap64Bit::UnmapPage(%#" B_PRIxADDR ")\n", address); + + ThreadCPUPinner pinner(thread_get_current_thread()); + + // Look up the page table for the virtual address. + uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), address, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (entry == NULL) + return B_ENTRY_NOT_FOUND; + + RecursiveLocker locker(fLock); + + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntry(entry); + + pinner.Unlock(); + + if ((oldEntry & X86_64_PTE_PRESENT) == 0) + return B_ENTRY_NOT_FOUND; + + fMapCount--; + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flags was set, since only then the entry could have been + // in any TLB. + InvalidatePage(address); + + Flush(); + + // NOTE: Between clearing the page table entry and Flush() other + // processors (actually even this processor with another thread of the + // same team) could still access the page in question via their cached + // entry. We can obviously lose a modified flag in this case, with the + // effect that the page looks unmodified (and might thus be recycled), + // but is actually modified. + // In most cases this is harmless, but for vm_remove_all_page_mappings() + // this is actually a problem. + // Interestingly FreeBSD seems to ignore this problem as well + // (cf. pmap_remove_all()), unless I've missed something. + } + + locker.Detach(); + // PageUnmapped() will unlock for us + + PageUnmapped(area, (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE, + (oldEntry & X86_64_PTE_ACCESSED) != 0, + (oldEntry & X86_64_PTE_DIRTY) != 0, updatePageQueue); + + return B_OK; +} + + +void +X86VMTranslationMap64Bit::UnmapPages(VMArea* area, addr_t base, size_t size, + bool updatePageQueue) +{ + if (size == 0) + return; + + addr_t start = base; + addr_t end = base + size - 1; + + TRACE("X86VMTranslationMap64Bit::UnmapPages(%p, %#" B_PRIxADDR ", %#" + B_PRIxADDR ")\n", area, start, end); + + VMAreaMappings queue; + + RecursiveLocker locker(fLock); + ThreadCPUPinner pinner(thread_get_current_thread()); + + do { + uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( + fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + NULL, fPageMapper, fMapCount); + if (pageTable == NULL) { + // Move on to the next page table. + start = ROUNDUP(start + 1, k64BitPageTableRange); + continue; + } + + for (uint32 index = start / B_PAGE_SIZE % k64BitTableEntryCount; + index < k64BitTableEntryCount && start < end; + index++, start += B_PAGE_SIZE) { + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntry( + &pageTable[index]); + if ((oldEntry & X86_64_PTE_PRESENT) == 0) + continue; + + fMapCount--; + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flags was set, since only then the entry could have + // been in any TLB. + InvalidatePage(start); + } + + if (area->cache_type != CACHE_TYPE_DEVICE) { + // get the page + vm_page* page = vm_lookup_page( + (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE); + ASSERT(page != NULL); + + DEBUG_PAGE_ACCESS_START(page); + + // transfer the accessed/dirty flags to the page + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) + page->accessed = true; + if ((oldEntry & X86_64_PTE_DIRTY) != 0) + page->modified = true; + + // remove the mapping object/decrement the wired_count of the + // page + if (area->wiring == B_NO_LOCK) { + vm_page_mapping* mapping = NULL; + vm_page_mappings::Iterator iterator + = page->mappings.GetIterator(); + while ((mapping = iterator.Next()) != NULL) { + if (mapping->area == area) + break; + } + + ASSERT(mapping != NULL); + + area->mappings.Remove(mapping); + page->mappings.Remove(mapping); + queue.Add(mapping); + } else + page->DecrementWiredCount(); + + if (!page->IsMapped()) { + atomic_add(&gMappedPagesCount, -1); + + if (updatePageQueue) { + if (page->Cache()->temporary) + vm_page_set_state(page, PAGE_STATE_INACTIVE); + else if (page->modified) + vm_page_set_state(page, PAGE_STATE_MODIFIED); + else + vm_page_set_state(page, PAGE_STATE_CACHED); + } + } + + DEBUG_PAGE_ACCESS_END(page); + } + } + + Flush(); + // flush explicitly, since we directly use the lock + } while (start != 0 && start < end); + + // TODO: As in UnmapPage() we can lose page dirty flags here. ATM it's not + // really critical here, as in all cases this method is used, the unmapped + // area range is unmapped for good (resized/cut) and the pages will likely + // be freed. + + locker.Unlock(); + + // free removed mappings + bool isKernelSpace = area->address_space == VMAddressSpace::Kernel(); + uint32 freeFlags = CACHE_DONT_WAIT_FOR_MEMORY + | (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0); + while (vm_page_mapping* mapping = queue.RemoveHead()) + object_cache_free(gPageMappingsObjectCache, mapping, freeFlags); +} + + +void +X86VMTranslationMap64Bit::UnmapArea(VMArea* area, bool deletingAddressSpace, + bool ignoreTopCachePageFlags) +{ + TRACE("X86VMTranslationMap64Bit::UnmapArea(%p)\n", area); + + if (area->cache_type == CACHE_TYPE_DEVICE || area->wiring != B_NO_LOCK) { + X86VMTranslationMap64Bit::UnmapPages(area, area->Base(), area->Size(), + true); + return; + } + + bool unmapPages = !deletingAddressSpace || !ignoreTopCachePageFlags; + + RecursiveLocker locker(fLock); + ThreadCPUPinner pinner(thread_get_current_thread()); + + VMAreaMappings mappings; + mappings.MoveFrom(&area->mappings); + + for (VMAreaMappings::Iterator it = mappings.GetIterator(); + vm_page_mapping* mapping = it.Next();) { + vm_page* page = mapping->page; + page->mappings.Remove(mapping); + + VMCache* cache = page->Cache(); + + bool pageFullyUnmapped = false; + if (!page->IsMapped()) { + atomic_add(&gMappedPagesCount, -1); + pageFullyUnmapped = true; + } + + if (unmapPages || cache != area->cache) { + addr_t address = area->Base() + + ((page->cache_offset * B_PAGE_SIZE) - area->cache_offset); + + uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), address, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (entry == NULL) { + panic("page %p has mapping for area %p (%#" B_PRIxADDR "), but " + "has no page table", page, area, address); + continue; + } + + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntry(entry); + + if ((oldEntry & X86_64_PTE_PRESENT) == 0) { + panic("page %p has mapping for area %p (%#" B_PRIxADDR "), but " + "has no page table entry", page, area, address); + continue; + } + + // transfer the accessed/dirty flags to the page and invalidate + // the mapping, if necessary + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + page->accessed = true; + + if (!deletingAddressSpace) + InvalidatePage(address); + } + + if ((oldEntry & X86_64_PTE_DIRTY) != 0) + page->modified = true; + + if (pageFullyUnmapped) { + DEBUG_PAGE_ACCESS_START(page); + + if (cache->temporary) + vm_page_set_state(page, PAGE_STATE_INACTIVE); + else if (page->modified) + vm_page_set_state(page, PAGE_STATE_MODIFIED); + else + vm_page_set_state(page, PAGE_STATE_CACHED); + + DEBUG_PAGE_ACCESS_END(page); + } + } + + fMapCount--; + } + + Flush(); + // flush explicitely, since we directly use the lock + + locker.Unlock(); + + bool isKernelSpace = area->address_space == VMAddressSpace::Kernel(); + uint32 freeFlags = CACHE_DONT_WAIT_FOR_MEMORY + | (isKernelSpace ? CACHE_DONT_LOCK_KERNEL_SPACE : 0); + while (vm_page_mapping* mapping = mappings.RemoveHead()) + object_cache_free(gPageMappingsObjectCache, mapping, freeFlags); +} + + +status_t +X86VMTranslationMap64Bit::Query(addr_t virtualAddress, + phys_addr_t* _physicalAddress, uint32* _flags) +{ + *_flags = 0; + *_physicalAddress = 0; + + ThreadCPUPinner pinner(thread_get_current_thread()); + + // Look up the page table for the virtual address. + uint64* pte = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), virtualAddress, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (pte == NULL) + return B_OK; + + uint64 entry = *pte; + + *_physicalAddress = entry & X86_64_PTE_ADDRESS_MASK; + + // Translate the page state flags. + if ((entry & X86_64_PTE_USER) != 0) { + *_flags |= ((entry & X86_64_PTE_WRITABLE) != 0 ? B_WRITE_AREA : 0) + | B_READ_AREA; + } + + *_flags |= ((entry & X86_64_PTE_WRITABLE) != 0 ? B_KERNEL_WRITE_AREA : 0) + | B_KERNEL_READ_AREA + | ((entry & X86_64_PTE_DIRTY) != 0 ? PAGE_MODIFIED : 0) + | ((entry & X86_64_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) + | ((entry & X86_64_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); + + TRACE("X86VMTranslationMap64Bit::Query(%#" B_PRIxADDR ") -> %#" + B_PRIxPHYSADDR ":\n", virtualAddress, *_physicalAddress); + + return B_OK; +} + + +status_t +X86VMTranslationMap64Bit::QueryInterrupt(addr_t virtualAddress, + phys_addr_t* _physicalAddress, uint32* _flags) +{ + *_flags = 0; + *_physicalAddress = 0; + + ThreadCPUPinner pinner(thread_get_current_thread()); + + // Look up the page table for the virtual address. + // FIXME: PageTableEntryForAddress uses GetPageTableAt() rather than + // InterruptGetPageTableAt(). This doesn't actually matter since in our + // page mapper both functions are the same, but perhaps this should be + // fixed for correctness. + uint64* pte = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), virtualAddress, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (pte == NULL) + return B_OK; + + uint64 entry = *pte; + + *_physicalAddress = entry & X86_64_PTE_ADDRESS_MASK; + + // Translate the page state flags. + if ((entry & X86_64_PTE_USER) != 0) { + *_flags |= ((entry & X86_64_PTE_WRITABLE) != 0 ? B_WRITE_AREA : 0) + | B_READ_AREA; + } + + *_flags |= ((entry & X86_64_PTE_WRITABLE) != 0 ? B_KERNEL_WRITE_AREA : 0) + | B_KERNEL_READ_AREA + | ((entry & X86_64_PTE_DIRTY) != 0 ? PAGE_MODIFIED : 0) + | ((entry & X86_64_PTE_ACCESSED) != 0 ? PAGE_ACCESSED : 0) + | ((entry & X86_64_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); + + TRACE("X86VMTranslationMap64Bit::QueryInterrupt(%#" B_PRIxADDR ") -> %#" + B_PRIxPHYSADDR ":\n", virtualAddress, *_physicalAddress); + + return B_OK; +} + + +status_t +X86VMTranslationMap64Bit::Protect(addr_t start, addr_t end, uint32 attributes, + uint32 memoryType) +{ + start = ROUNDDOWN(start, B_PAGE_SIZE); + if (start >= end) + return B_OK; + + TRACE("X86VMTranslationMap64Bit::Protect(%#" B_PRIxADDR ", %#" B_PRIxADDR + ", %#" B_PRIx32 ")\n", start, end, attributes); + + // compute protection flags + uint64 newProtectionFlags = 0; + if ((attributes & B_USER_PROTECTION) != 0) { + newProtectionFlags = X86_64_PTE_USER; + if ((attributes & B_WRITE_AREA) != 0) + newProtectionFlags |= X86_64_PTE_WRITABLE; + } else if ((attributes & B_KERNEL_WRITE_AREA) != 0) + newProtectionFlags = X86_64_PTE_WRITABLE; + + ThreadCPUPinner pinner(thread_get_current_thread()); + + do { + uint64* pageTable = X86PagingMethod64Bit::PageTableForAddress( + fPagingStructures->VirtualPML4(), start, fIsKernelMap, false, + NULL, fPageMapper, fMapCount); + if (pageTable == NULL) { + // Move on to the next page table. + start = ROUNDUP(start + 1, k64BitPageTableRange); + continue; + } + + for (uint32 index = start / B_PAGE_SIZE % k64BitTableEntryCount; + index < k64BitTableEntryCount && start < end; + index++, start += B_PAGE_SIZE) { + uint64 entry = pageTable[index]; + if ((entry & X86_64_PTE_PRESENT) == 0) + continue; + + TRACE("X86VMTranslationMap64Bit::Protect(): protect page %#" + B_PRIxADDR "\n", start); + + // set the new protection flags -- we want to do that atomically, + // without changing the accessed or dirty flag + uint64 oldEntry; + while (true) { + oldEntry = X86PagingMethod64Bit::TestAndSetTableEntry( + &pageTable[index], + (entry & ~(X86_64_PTE_PROTECTION_MASK + | X86_64_PTE_MEMORY_TYPE_MASK)) + | newProtectionFlags + | X86PagingMethod64Bit::MemoryTypeToPageTableEntryFlags( + memoryType), + entry); + if (oldEntry == entry) + break; + entry = oldEntry; + } + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flag was set, since only then the entry could have + // been in any TLB. + InvalidatePage(start); + } + } + } while (start != 0 && start < end); + + return B_OK; +} + + +status_t +X86VMTranslationMap64Bit::ClearFlags(addr_t address, uint32 flags) +{ + TRACE("X86VMTranslationMap64Bit::ClearFlags(%#" B_PRIxADDR ", %#" B_PRIx32 + ")\n", address, flags); + + ThreadCPUPinner pinner(thread_get_current_thread()); + + uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), address, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (entry == NULL) + return B_OK; + + uint64 flagsToClear = ((flags & PAGE_MODIFIED) ? X86_64_PTE_DIRTY : 0) + | ((flags & PAGE_ACCESSED) ? X86_64_PTE_ACCESSED : 0); + + uint64 oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags(entry, + flagsToClear); + + if ((oldEntry & flagsToClear) != 0) + InvalidatePage(address); + + return B_OK; +} + + +bool +X86VMTranslationMap64Bit::ClearAccessedAndModified(VMArea* area, addr_t address, + bool unmapIfUnaccessed, bool& _modified) +{ + ASSERT(address % B_PAGE_SIZE == 0); + + TRACE("X86VMTranslationMap64Bit::ClearAccessedAndModified(%#" B_PRIxADDR + ")\n", address); + + RecursiveLocker locker(fLock); + ThreadCPUPinner pinner(thread_get_current_thread()); + + uint64* entry = X86PagingMethod64Bit::PageTableEntryForAddress( + fPagingStructures->VirtualPML4(), address, fIsKernelMap, + false, NULL, fPageMapper, fMapCount); + if (entry == NULL) + return false; + + uint64 oldEntry; + + if (unmapIfUnaccessed) { + while (true) { + oldEntry = *entry; + if ((oldEntry & X86_64_PTE_PRESENT) == 0) { + // page mapping not valid + return false; + } + + if (oldEntry & X86_64_PTE_ACCESSED) { + // page was accessed -- just clear the flags + oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags(entry, + X86_64_PTE_ACCESSED | X86_64_PTE_DIRTY); + break; + } + + // page hasn't been accessed -- unmap it + if (X86PagingMethod64Bit::TestAndSetTableEntry(entry, 0, oldEntry) + == oldEntry) { + break; + } + + // something changed -- check again + } + } else { + oldEntry = X86PagingMethod64Bit::ClearTableEntryFlags(entry, + X86_64_PTE_ACCESSED | X86_64_PTE_DIRTY); + } + + pinner.Unlock(); + + _modified = (oldEntry & X86_64_PTE_DIRTY) != 0; + + if ((oldEntry & X86_64_PTE_ACCESSED) != 0) { + // Note, that we only need to invalidate the address, if the + // accessed flags was set, since only then the entry could have been + // in any TLB. + InvalidatePage(address); + Flush(); + + return true; + } + + if (!unmapIfUnaccessed) + return false; + + // We have unmapped the address. Do the "high level" stuff. + + fMapCount--; + + locker.Detach(); + // UnaccessedPageUnmapped() will unlock for us + + UnaccessedPageUnmapped(area, + (oldEntry & X86_64_PTE_ADDRESS_MASK) / B_PAGE_SIZE); + + return false; +} + + +X86PagingStructures* +X86VMTranslationMap64Bit::PagingStructures() const +{ + return fPagingStructures; +} diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h index 2e0c000575..7a9b449a70 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.h @@ -1,5 +1,6 @@ /* * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #ifndef KERNEL_ARCH_X86_PAGING_64BIT_X86_VM_TRANSLATION_MAP_64BIT_H @@ -9,7 +10,60 @@ #include "paging/X86VMTranslationMap.h" +struct X86PagingStructures64Bit; +struct X86VMTranslationMap64Bit : X86VMTranslationMap { + X86VMTranslationMap64Bit(); + virtual ~X86VMTranslationMap64Bit(); + + status_t Init(bool kernel); + + virtual size_t MaxPagesNeededToMap(addr_t start, + addr_t end) const; + + virtual status_t Map(addr_t virtualAddress, + phys_addr_t physicalAddress, + uint32 attributes, uint32 memoryType, + vm_page_reservation* reservation); + virtual status_t Unmap(addr_t start, addr_t end); + + virtual status_t DebugMarkRangePresent(addr_t start, addr_t end, + bool markPresent); + + virtual status_t UnmapPage(VMArea* area, addr_t address, + bool updatePageQueue); + virtual void UnmapPages(VMArea* area, addr_t base, + size_t size, bool updatePageQueue); + virtual void UnmapArea(VMArea* area, + bool deletingAddressSpace, + bool ignoreTopCachePageFlags); + + virtual status_t Query(addr_t virtualAddress, + phys_addr_t* _physicalAddress, + uint32* _flags); + virtual status_t QueryInterrupt(addr_t virtualAddress, + phys_addr_t* _physicalAddress, + uint32* _flags); + + virtual status_t Protect(addr_t base, addr_t top, + uint32 attributes, uint32 memoryType); + + virtual status_t ClearFlags(addr_t virtualAddress, + uint32 flags); + + virtual bool ClearAccessedAndModified( + VMArea* area, addr_t address, + bool unmapIfUnaccessed, + bool& _modified); + + virtual X86PagingStructures* PagingStructures() const; + inline X86PagingStructures64Bit* PagingStructures64Bit() const + { return fPagingStructures; } + +private: + X86PagingStructures64Bit* fPagingStructures; +}; + #endif // KERNEL_ARCH_X86_PAGING_64BIT_X86_VM_TRANSLATION_MAP_64BIT_H diff --git a/src/system/kernel/arch/x86/paging/64bit/paging.h b/src/system/kernel/arch/x86/paging/64bit/paging.h index d0f077cf01..2cb4fb4b06 100644 --- a/src/system/kernel/arch/x86/paging/64bit/paging.h +++ b/src/system/kernel/arch/x86/paging/64bit/paging.h @@ -2,11 +2,79 @@ * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. */ -#ifndef KERNEL_ARCH_X86_PAGING_PAE_PAGING_H -#define KERNEL_ARCH_X86_PAGING_PAE_PAGING_H +#ifndef KERNEL_ARCH_X86_PAGING_64BIT_PAGING_H +#define KERNEL_ARCH_X86_PAGING_64BIT_PAGING_H #include -#endif // KERNEL_ARCH_X86_PAGING_PAE_PAGING_H +// PML4 entry bits. +#define X86_64_PML4E_PRESENT (1LL << 0) +#define X86_64_PML4E_WRITABLE (1LL << 1) +#define X86_64_PML4E_USER (1LL << 2) +#define X86_64_PML4E_WRITE_THROUGH (1LL << 3) +#define X86_64_PML4E_CACHING_DISABLED (1LL << 4) +#define X86_64_PML4E_ACCESSED (1LL << 5) +#define X86_64_PML4E_NOT_EXECUTABLE (1LL << 63) +#define X86_64_PML4E_ADDRESS_MASK 0x000ffffffffff000L + +// PDPT entry bits. +#define X86_64_PDPTE_PRESENT (1LL << 0) +#define X86_64_PDPTE_WRITABLE (1LL << 1) +#define X86_64_PDPTE_USER (1LL << 2) +#define X86_64_PDPTE_WRITE_THROUGH (1LL << 3) +#define X86_64_PDPTE_CACHING_DISABLED (1LL << 4) +#define X86_64_PDPTE_ACCESSED (1LL << 5) +#define X86_64_PDPTE_DIRTY (1LL << 6) +#define X86_64_PDPTE_LARGE_PAGE (1LL << 7) +#define X86_64_PDPTE_GLOBAL (1LL << 8) +#define X86_64_PDPTE_PAT (1LL << 12) +#define X86_64_PDPTE_NOT_EXECUTABLE (1LL << 63) +#define X86_64_PDPTE_ADDRESS_MASK 0x000ffffffffff000L + +// Page directory entry bits. +#define X86_64_PDE_PRESENT (1LL << 0) +#define X86_64_PDE_WRITABLE (1LL << 1) +#define X86_64_PDE_USER (1LL << 2) +#define X86_64_PDE_WRITE_THROUGH (1LL << 3) +#define X86_64_PDE_CACHING_DISABLED (1LL << 4) +#define X86_64_PDE_ACCESSED (1LL << 5) +#define X86_64_PDE_DIRTY (1LL << 6) +#define X86_64_PDE_LARGE_PAGE (1LL << 7) +#define X86_64_PDE_GLOBAL (1LL << 8) +#define X86_64_PDE_PAT (1LL << 12) +#define X86_64_PDE_NOT_EXECUTABLE (1LL << 63) +#define X86_64_PDE_ADDRESS_MASK 0x000ffffffffff000L + +// Page table entry bits. +#define X86_64_PTE_PRESENT (1LL << 0) +#define X86_64_PTE_WRITABLE (1LL << 1) +#define X86_64_PTE_USER (1LL << 2) +#define X86_64_PTE_WRITE_THROUGH (1LL << 3) +#define X86_64_PTE_CACHING_DISABLED (1LL << 4) +#define X86_64_PTE_ACCESSED (1LL << 5) +#define X86_64_PTE_DIRTY (1LL << 6) +#define X86_64_PTE_PAT (1LL << 7) +#define X86_64_PTE_GLOBAL (1LL << 8) +#define X86_64_PTE_NOT_EXECUTABLE (1LL << 63) +#define X86_64_PTE_ADDRESS_MASK 0x000ffffffffff000L +#define X86_64_PTE_PROTECTION_MASK (X86_64_PTE_WRITABLE | X86_64_PTE_USER) +#define X86_64_PTE_MEMORY_TYPE_MASK (X86_64_PTE_WRITE_THROUGH \ + | X86_64_PTE_CACHING_DISABLED) + + +static const size_t k64BitPageTableRange = 0x200000L; +static const size_t k64BitPageDirectoryRange = 0x40000000L; +static const size_t k64BitPDPTRange = 0x8000000000L; + +static const size_t k64BitTableEntryCount = 512; + + +#define VADDR_TO_PML4E(va) (((va) & 0x0000fffffffff000L) / k64BitPDPTRange) +#define VADDR_TO_PDPTE(va) (((va) % k64BitPDPTRange) / k64BitPageDirectoryRange) +#define VADDR_TO_PDE(va) (((va) % k64BitPageDirectoryRange) / k64BitPageTableRange) +#define VADDR_TO_PTE(va) (((va) % k64BitPageTableRange) / B_PAGE_SIZE) + + +#endif // KERNEL_ARCH_X86_PAGING_64BIT_PAGING_H diff --git a/src/system/kernel/arch/x86/paging/X86PagingMethod.h b/src/system/kernel/arch/x86/paging/X86PagingMethod.h index 964f425f92..e80c4c7a14 100644 --- a/src/system/kernel/arch/x86/paging/X86PagingMethod.h +++ b/src/system/kernel/arch/x86/paging/X86PagingMethod.h @@ -8,6 +8,8 @@ #include +#include + struct kernel_args; struct VMPhysicalPageMapper; @@ -30,7 +32,7 @@ public: addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)) + page_num_t (*get_free_page)(kernel_args*)) = 0; virtual bool IsKernelPageAccessible(addr_t virtualAddress, diff --git a/src/system/kernel/arch/x86/paging/X86PagingStructures.h b/src/system/kernel/arch/x86/paging/X86PagingStructures.h index f7cfb6a54c..fe8b9d9a94 100644 --- a/src/system/kernel/arch/x86/paging/X86PagingStructures.h +++ b/src/system/kernel/arch/x86/paging/X86PagingStructures.h @@ -16,7 +16,7 @@ struct X86PagingStructures : DeferredDeletable { - uint32 pgdir_phys; + phys_addr_t pgdir_phys; vint32 ref_count; vint32 active_on_cpus; // mask indicating on which CPUs the map is currently used diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp index 4156b3ad33..3a3115ff4d 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.cpp @@ -629,7 +629,7 @@ X86PagingMethodPAE::CreateTranslationMap(bool kernel, VMTranslationMap** _map) status_t X86PagingMethodPAE::MapEarly(kernel_args* args, addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)) + page_num_t (*get_free_page)(kernel_args*)) { // check to see if a page table exists for this range pae_page_directory_entry* pageDirEntry = PageDirEntryForAddress( diff --git a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.h b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.h index e1232d05bc..6d6b1ed1ab 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.h +++ b/src/system/kernel/arch/x86/paging/pae/X86PagingMethodPAE.h @@ -39,7 +39,7 @@ public: addr_t virtualAddress, phys_addr_t physicalAddress, uint8 attributes, - phys_addr_t (*get_free_page)(kernel_args*)); + page_num_t (*get_free_page)(kernel_args*)); virtual bool IsKernelPageAccessible(addr_t virtualAddress, uint32 protection); diff --git a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp index 8f086b522d..8d6853689b 100644 --- a/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp +++ b/src/system/kernel/arch/x86/paging/pae/X86VMTranslationMapPAE.cpp @@ -697,7 +697,7 @@ X86VMTranslationMapPAE::Query(addr_t virtualAddress, | ((entry & X86_PAE_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); TRACE("X86VMTranslationMapPAE::Query(%#" B_PRIxADDR ") -> %#" - B_PRIxPHYSADDR ":\n", *_physicalAddress, virtualAddress); + B_PRIxPHYSADDR ":\n", virtualAddress, *_physicalAddress); return B_OK; } @@ -870,7 +870,7 @@ X86VMTranslationMapPAE::ClearAccessedAndModified(VMArea* area, addr_t address, { ASSERT(address % B_PAGE_SIZE == 0); - TRACE("X86VMTranslationMap32Bit::ClearAccessedAndModified(%#" B_PRIxADDR + TRACE("X86VMTranslationMapPAE::ClearAccessedAndModified(%#" B_PRIxADDR ")\n", address); pae_page_directory_entry* pageDirEntry From ab7726a2c4bafe6e4d4937c1fb6c80f9281d9fbc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 6 Jul 2012 14:04:07 +0100 Subject: [PATCH 076/273] Temporary fix for create_preloaded_image_areas. Will be replaced with a typedef later on. --- src/system/kernel/vm/vm.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index e30c739596..bedf91085e 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3540,13 +3540,16 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size) } -// TODO x86_64: hardcoding elf32 is temporary. static void -create_preloaded_image_areas(struct preloaded_elf32_image* image) +create_preloaded_image_areas(struct preloaded_image* _image) { -#ifdef __x86_64__ - panic("fix this"); + // TODO: Make this a typedef somewhere. Will be done when I implement + // ELF loading for x86_64. +#ifdef B_HAIKU_64_BIT + preloaded_elf64_image* image = static_cast(_image); #else + preloaded_elf32_image* image = static_cast(_image); +#endif char name[B_OS_NAME_LENGTH]; void* address; int32 length; @@ -3577,7 +3580,6 @@ create_preloaded_image_areas(struct preloaded_elf32_image* image) image->data_region.id = create_area(name, &address, B_EXACT_ADDRESS, PAGE_ALIGN(image->data_region.size), B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); -#endif } @@ -3850,13 +3852,11 @@ vm_init(kernel_args* args) allocate_kernel_args(args); - create_preloaded_image_areas(static_cast( - (void*)args->kernel_image)); + create_preloaded_image_areas(args->kernel_image); // allocate areas for preloaded images for (image = args->preloaded_images; image != NULL; image = image->next) - create_preloaded_image_areas( - static_cast(image)); + create_preloaded_image_areas(image); // allocate kernel stacks for (i = 0; i < args->num_cpus; i++) { From 84bf29f97b5ff5f1ace8dfee48d035cba0b4fb75 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 6 Jul 2012 14:17:48 +0100 Subject: [PATCH 077/273] Compile in arch_platform.cpp for x86_64. The apm_init call is disabled for x86_64, APM is 32-bit only. --- headers/private/kernel/arch/x86/apm.h | 2 ++ src/system/kernel/arch/x86/64/stubs.cpp | 22 -------------------- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_platform.cpp | 3 +++ 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/headers/private/kernel/arch/x86/apm.h b/headers/private/kernel/arch/x86/apm.h index 675ed5a6be..cc557efeb2 100644 --- a/headers/private/kernel/arch/x86/apm.h +++ b/headers/private/kernel/arch/x86/apm.h @@ -50,6 +50,7 @@ typedef struct apm_info { #ifndef _BOOT_MODE +#ifndef __x86_64__ #ifdef __cplusplus extern "C" { #endif @@ -60,6 +61,7 @@ status_t apm_init(struct kernel_args *args); #ifdef __cplusplus } #endif +#endif // !__x86_64__ #endif // !_BOOT_MODE #endif /* KERNEL_APM_H */ diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index fe6b42b829..d98116faaf 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -244,27 +243,6 @@ arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, } -status_t -arch_platform_init(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_platform_init_post_vm(struct kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_platform_init_post_thread(struct kernel_args *args) -{ - return B_OK; -} - - status_t arch_rtc_init(struct kernel_args *args, struct real_time_data *data) { diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index c45f2d1f12..207abb9287 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -47,7 +47,6 @@ if $(TARGET_ARCH) = x86_64 { arch_commpage.cpp arch_debug.cpp arch_elf.cpp - arch_platform.cpp arch_real_time_clock.cpp arch_smp.cpp arch_thread.cpp @@ -90,6 +89,7 @@ local archGenericSources = arch_cpu.cpp arch_debug_console.cpp arch_int.cpp + arch_platform.cpp arch_vm.cpp arch_vm_translation_map.cpp pic.cpp diff --git a/src/system/kernel/arch/x86/arch_platform.cpp b/src/system/kernel/arch/x86/arch_platform.cpp index 9dc40abf7d..d967139701 100644 --- a/src/system/kernel/arch/x86/arch_platform.cpp +++ b/src/system/kernel/arch/x86/arch_platform.cpp @@ -29,7 +29,10 @@ arch_platform_init_post_vm(struct kernel_args *args) status_t arch_platform_init_post_thread(struct kernel_args *args) { + // APM is not supported on x86_64. +#ifndef __x86_64__ apm_init(args); +#endif return B_OK; } From 15feb60325be086823e80a3468f7aab2bfbc9f7d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 6 Jul 2012 14:34:50 +0100 Subject: [PATCH 078/273] A few improvements suggested by Ingo. --- headers/private/kernel/arch/x86/arch_kernel.h | 15 ++++++------ headers/private/kernel/kernel.h | 4 ++++ src/system/boot/loader/elf.cpp | 10 ++++---- src/system/boot/platform/bios_ia32/long.cpp | 8 +++---- src/system/boot/platform/bios_ia32/mmu.cpp | 24 +++++++++---------- src/system/kernel/arch/x86/64/stubs.cpp | 3 ++- src/system/kernel/arch/x86/arch_debug.cpp | 3 ++- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 14413f9083..87e676b58d 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -18,23 +18,22 @@ // 32-bit and 64-bit kernel load addresses. -#define KERNEL_BASE 0x80000000 -#define KERNEL_BASE_64BIT 0xffffffff80000000ll +#define KERNEL_LOAD_BASE 0x80000000 +#define KERNEL_LOAD_BASE_64BIT 0xffffffff80000000ll #elif defined(__x86_64__) // Base of the kernel address space. -// When compiling the bootloader, KERNEL_BASE is set to the x86 base address, -// KERNEL_BASE_64BIT is set to where the kernel loaded to. -// For the kernel, KERNEL_BASE is the base of the kernel address space. This is -// NOT the address where the kernel is loaded to: the kernel is loaded in the -// top 2GB of the virtual address space as required by GCC's kernel code model. -// The whole kernel address space is the top 512GB of the address space. +// KERNEL_BASE is the base of the kernel address space. This differs from the +// address where the kernel is loaded to: the kernel is loaded in the top 2GB +// of the virtual address space as required by GCC's kernel code model. The +// whole kernel address space is the top 512GB of the address space. #define KERNEL_BASE 0xffffff8000000000 #define KERNEL_SIZE 0x8000000000 #define KERNEL_TOP (KERNEL_BASE + (KERNEL_SIZE - 1)) +#define KERNEL_LOAD_BASE 0xffffffff80000000 // Kernel physical memory map area. #define KERNEL_PMAP_BASE 0xffffff0000000000 diff --git a/headers/private/kernel/kernel.h b/headers/private/kernel/kernel.h index 28041cba1c..ec5a166f56 100644 --- a/headers/private/kernel/kernel.h +++ b/headers/private/kernel/kernel.h @@ -15,6 +15,10 @@ #include +#ifndef KERNEL_LOAD_BASE +# define KERNEL_LOAD_BASE KERNEL_BASE +#endif + // macro to check whether an address is in the kernel address space (avoid // always-true checks) #if KERNEL_BASE == 0 diff --git a/src/system/boot/loader/elf.cpp b/src/system/boot/loader/elf.cpp index 8494ff7f6d..a08a297ea2 100644 --- a/src/system/boot/loader/elf.cpp +++ b/src/system/boot/loader/elf.cpp @@ -116,8 +116,8 @@ struct ELF64Class { AllocateRegion(AddrType* _address, AddrType size, uint8 protection, void **_mappedAddress) { - // Assume the real 64-bit base address is KERNEL_BASE_64BIT and the - // mappings in the loader address space are at KERNEL_BASE. + // Assume the real 64-bit base address is KERNEL_LOAD_BASE_64BIT and + // the mappings in the loader address space are at KERNEL_LOAD_BASE. void* address = (void*)(addr_t)(*_address & 0xffffffff); @@ -127,14 +127,16 @@ struct ELF64Class { return status; *_mappedAddress = address; - *_address = (AddrType)(addr_t)address + KERNEL_BASE_64BIT - KERNEL_BASE; + *_address = (AddrType)(addr_t)address + KERNEL_LOAD_BASE_64BIT + - KERNEL_LOAD_BASE; return B_OK; } static inline void* Map(AddrType address) { - return (void*)(addr_t)(address - KERNEL_BASE_64BIT + KERNEL_BASE); + return (void*)(addr_t)(address - KERNEL_LOAD_BASE_64BIT + + KERNEL_LOAD_BASE); } }; diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 2a942df653..16fd1ae0f1 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -36,7 +36,7 @@ static const uint64 kPageMappingFlags = 0x103; static inline uint64 fix_address(uint64 address) { - return address - KERNEL_BASE + KERNEL_BASE_64BIT; + return address - KERNEL_LOAD_BASE + KERNEL_LOAD_BASE_64BIT; } @@ -157,7 +157,7 @@ long_mmu_init() pdpt[510] = physicalAddress | kTableMappingFlags; // Store the virtual memory usage information. - gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE_64BIT; + gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64BIT; gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage(); gKernelArgs.num_virtual_allocated_ranges = 1; @@ -176,14 +176,14 @@ long_mmu_init() } // Get the physical address to map. - if (!mmu_get_virtual_mapping(KERNEL_BASE + (i * B_PAGE_SIZE), + if (!mmu_get_virtual_mapping(KERNEL_LOAD_BASE + (i * B_PAGE_SIZE), &physicalAddress)) continue; pageTable[i % 512] = physicalAddress | kPageMappingFlags; } - gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_BASE_64BIT + gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64BIT + gKernelArgs.virtual_allocated_range[0].size, 0x200000); // Sort the address ranges. diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index ba4779e255..1046b70116 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -78,7 +78,7 @@ static uint32 *sPageDirectory = 0; #ifdef _PXE_ENV static addr_t sNextPhysicalAddress = 0x112000; -static addr_t sNextVirtualAddress = KERNEL_BASE + kMaxKernelSize; +static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize; static addr_t sNextPageTableAddress = 0x7d000; static const uint32 kPageTableRegionEnd = 0x8b000; @@ -87,7 +87,7 @@ static const uint32 kPageTableRegionEnd = 0x8b000; #else static addr_t sNextPhysicalAddress = 0x100000; -static addr_t sNextVirtualAddress = KERNEL_BASE + kMaxKernelSize; +static addr_t sNextVirtualAddress = KERNEL_LOAD_BASE + kMaxKernelSize; static addr_t sNextPageTableAddress = 0x90000; static const uint32 kPageTableRegionEnd = 0x9e000; @@ -195,7 +195,7 @@ unmap_page(addr_t virtualAddress) { TRACE("unmap_page(virtualAddress = %p)\n", (void *)virtualAddress); - if (virtualAddress < KERNEL_BASE) { + if (virtualAddress < KERNEL_LOAD_BASE) { panic("unmap_page: asked to unmap invalid page %p!\n", (void *)virtualAddress); } @@ -220,7 +220,7 @@ map_page(addr_t virtualAddress, addr_t physicalAddress, uint32 flags) TRACE("map_page: vaddr 0x%lx, paddr 0x%lx\n", virtualAddress, physicalAddress); - if (virtualAddress < KERNEL_BASE) { + if (virtualAddress < KERNEL_LOAD_BASE) { panic("map_page: asked to map invalid page %p!\n", (void *)virtualAddress); } @@ -397,8 +397,8 @@ mmu_allocate(void *virtualAddress, size_t size) addr_t address = (addr_t)virtualAddress; // is the address within the valid range? - if (address < KERNEL_BASE - || address + size >= KERNEL_BASE + kMaxKernelSize) + if (address < KERNEL_LOAD_BASE + || address + size >= KERNEL_LOAD_BASE + kMaxKernelSize) return NULL; for (uint32 i = 0; i < size; i++) { @@ -479,7 +479,7 @@ mmu_free(void *virtualAddress, size_t size) size = (size + pageOffset + B_PAGE_SIZE - 1) / B_PAGE_SIZE * B_PAGE_SIZE; // is the address within the valid range? - if (address < KERNEL_BASE || address + size > sNextVirtualAddress) { + if (address < KERNEL_LOAD_BASE || address + size > sNextVirtualAddress) { panic("mmu_free: asked to unmap out of range region (%p, size %lx)\n", (void *)address, size); } @@ -500,14 +500,14 @@ mmu_free(void *virtualAddress, size_t size) size_t mmu_get_virtual_usage() { - return sNextVirtualAddress - KERNEL_BASE; + return sNextVirtualAddress - KERNEL_LOAD_BASE; } bool mmu_get_virtual_mapping(addr_t virtualAddress, addr_t *_physicalAddress) { - if (virtualAddress < KERNEL_BASE) { + if (virtualAddress < KERNEL_LOAD_BASE) { panic("mmu_get_virtual_mapping: asked to lookup invalid page %p!\n", (void *)virtualAddress); } @@ -607,9 +607,9 @@ mmu_init_for_kernel(void) // Save the memory we've virtually allocated (for the kernel and other // stuff) - gKernelArgs.virtual_allocated_range[0].start = KERNEL_BASE; + gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE; gKernelArgs.virtual_allocated_range[0].size - = sNextVirtualAddress - KERNEL_BASE; + = sNextVirtualAddress - KERNEL_LOAD_BASE; gKernelArgs.num_virtual_allocated_ranges = 1; // sort the address ranges @@ -654,7 +654,7 @@ mmu_init(void) { TRACE("mmu_init\n"); - gKernelArgs.arch_args.virtual_end = KERNEL_BASE; + gKernelArgs.arch_args.virtual_end = KERNEL_LOAD_BASE; gKernelArgs.physical_allocated_range[0].start = sNextPhysicalAddress; gKernelArgs.physical_allocated_range[0].size = 0; diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index d98116faaf..97564aa547 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -94,7 +94,8 @@ static bool is_iframe(addr_t frame) { addr_t previousFrame = *(addr_t*)frame; - return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0); + return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0 + && previousFrame != 0); } diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index f00cb70f67..e8b90927d7 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -469,7 +469,8 @@ is_iframe(Thread* thread, addr_t frame) return false; addr_t previousFrame = *(addr_t*)frame; - return ((previousFrame & ~IFRAME_TYPE_MASK) == 0 && previousFrame != 0); + return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0 + && previousFrame != 0); } From c15176264b7fa5b4e20b4692d30ed9403fd9c71b Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 6 Jul 2012 15:24:02 +0100 Subject: [PATCH 079/273] Compile APIC and timer code for x86_64, and create an area for the IDT. --- src/system/kernel/arch/x86/64/int.cpp | 10 ++++++++-- src/system/kernel/arch/x86/64/stubs.cpp | 23 +---------------------- src/system/kernel/arch/x86/Jamfile | 14 +++++++------- src/system/kernel/arch/x86/apic.cpp | 5 +++-- src/system/kernel/arch/x86/arch_timer.cpp | 1 - src/system/kernel/vm/vm.cpp | 2 +- 6 files changed, 20 insertions(+), 35 deletions(-) diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index 849777b96c..bbc5850ebb 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -11,6 +11,8 @@ #include #include +#include +#include #include #include @@ -187,9 +189,13 @@ arch_int_init_post_vm(kernel_args* args) { // Always init the local apic as it can be used for timers even if we // don't end up using the io apic - //apic_init(args); + apic_init(args); - // TODO: create area for IDT. + // Create an area for the IDT. + area_id area = create_area("idt", (void**)&sIDT, B_EXACT_ADDRESS, + B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + if (area < 0) + return area; return B_OK; } diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 97564aa547..041e17f525 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -331,7 +331,7 @@ arch_thread_init(struct kernel_args *args) status_t arch_team_init_team_struct(Team *p, bool kernel) { - return B_ERROR; + return B_OK; } @@ -415,27 +415,6 @@ arch_restore_fork_frame(struct arch_fork_arg* arg) } -void -arch_timer_set_hardware_timer(bigtime_t timeout) -{ - -} - - -void -arch_timer_clear_hardware_timer(void) -{ - -} - - -int -arch_init_timer(kernel_args *args) -{ - return 0; -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 207abb9287..70d101314b 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -50,10 +50,8 @@ if $(TARGET_ARCH) = x86_64 { arch_real_time_clock.cpp arch_smp.cpp arch_thread.cpp - arch_timer.cpp arch_system_info.cpp arch_user_debugger.cpp - apic.cpp apm.cpp bios.cpp ioapic.cpp @@ -77,11 +75,6 @@ if $(TARGET_ARCH) = x86_64 { X86PagingMethodPAE.cpp X86PagingStructuresPAE.cpp X86VMTranslationMapPAE.cpp - - # timers - x86_apic.cpp - x86_hpet.cpp - x86_pit.cpp ; } @@ -90,8 +83,10 @@ local archGenericSources = arch_debug_console.cpp arch_int.cpp arch_platform.cpp + arch_timer.cpp arch_vm.cpp arch_vm_translation_map.cpp + apic.cpp pic.cpp # paging @@ -99,6 +94,11 @@ local archGenericSources = X86PagingMethod.cpp X86PagingStructures.cpp X86VMTranslationMap.cpp + + # timers + x86_apic.cpp + x86_hpet.cpp + x86_pit.cpp ; KernelMergeObject kernel_arch_x86.o : diff --git a/src/system/kernel/arch/x86/apic.cpp b/src/system/kernel/arch/x86/apic.cpp index 2c83935402..70f662cbde 100644 --- a/src/system/kernel/arch/x86/apic.cpp +++ b/src/system/kernel/arch/x86/apic.cpp @@ -88,8 +88,9 @@ apic_init(kernel_args *args) status_t apic_per_cpu_init(kernel_args *args, int32 cpu) { - dprintf("setting up apic for CPU %ld: apic id %lu, version %lu\n", cpu, - apic_local_id(), apic_read(APIC_VERSION)); + dprintf("setting up apic for CPU %" B_PRId32 ": apic id %" B_PRIu32 ", " + "version %" B_PRIu32 "\n", cpu, apic_local_id(), + apic_read(APIC_VERSION)); /* set spurious interrupt vector to 0xff */ uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00; diff --git a/src/system/kernel/arch/x86/arch_timer.cpp b/src/system/kernel/arch/x86/arch_timer.cpp index 3ee378a905..2248afa4fd 100644 --- a/src/system/kernel/arch/x86/arch_timer.cpp +++ b/src/system/kernel/arch/x86/arch_timer.cpp @@ -24,7 +24,6 @@ #include #include -#include "interrupts.h" //#define TRACE_TIMER #ifdef TRACE_TIMER diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index bedf91085e..040893537f 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -60,7 +60,7 @@ //#define TRACE_VM -#define TRACE_FAULTS +//#define TRACE_FAULTS #ifdef TRACE_VM # define TRACE(x) dprintf x #else From 5c7d52183c2182761151ba2f8f72bb7b39e50053 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 8 Jul 2012 10:16:44 +0100 Subject: [PATCH 080/273] Implemented system_time() for x86_64. * Uses 64-bit multiplication, special handling for CPUs clocked < 1 GHz in system_time_nsecs() not required like on x86. * Tested against a straight conversion of the x86 version, noticably faster with a large number of system_time() calls. --- headers/private/kernel/arch/x86/arch_cpu.h | 7 +- src/system/kernel/arch/x86/arch_cpu.cpp | 7 + .../libroot/os/arch/x86_64/system_time_asm.S | 142 ++++-------------- 3 files changed, 45 insertions(+), 111 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index f688a206cb..204c901814 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -367,9 +367,14 @@ extern "C" { struct arch_thread; - +#ifdef __x86_64__ +void __x86_setup_system_time(uint64 conversionFactor, + uint64 conversionFactorNsecs); +#else void __x86_setup_system_time(uint32 conversionFactor, uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); +#endif + void x86_context_switch(struct arch_thread* oldState, struct arch_thread* newState); void x86_userspace_thread_exit(void); diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index a618504d7f..6a7a2069b1 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -820,6 +820,12 @@ arch_cpu_init(kernel_args* args) uint32 conversionFactor = args->arch_args.system_time_cv_factor; uint64 conversionFactorNsecs = (uint64)conversionFactor * 1000; +#ifdef __x86_64__ + // The x86_64 system_time() implementation uses 64-bit multiplication and + // therefore shifting is not necessary for low frequencies (it's also not + // too likely that there'll be any x86_64 CPUs clocked under 1GHz). + __x86_setup_system_time(conversionFactor, conversionFactorNsecs); +#else if (conversionFactorNsecs >> 32 != 0) { // the TSC frequency is < 1 GHz, which forces us to shift the factor __x86_setup_system_time(conversionFactor, conversionFactorNsecs >> 16, @@ -828,6 +834,7 @@ arch_cpu_init(kernel_args* args) // the TSC frequency is >= 1 GHz __x86_setup_system_time(conversionFactor, conversionFactorNsecs, false); } +#endif return B_OK; } diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S index d6df8fa806..f63bdf35ba 100644 --- a/src/system/libroot/os/arch/x86_64/system_time_asm.S +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -7,143 +7,65 @@ * Distributed under the terms of the NewOS License. */ + #include -FUNCTION(__x86_setup_system_time): - ret -FUNCTION_END(__x86_setup_system_time) -// TODO: Implement these. - -/* int64 system_time(); */ -FUNCTION(system_time): - ud2a - ret -FUNCTION_END(system_time) - - -/* int64 system_time_nsecs(); */ -FUNCTION(system_time_nsecs): - ud2a - ret -FUNCTION_END(system_time_nsecs) - -#if 0 /* saves the conversion factor needed for system_time */ -.lcomm cv_factor 4 -.lcomm cv_factor_nsecs 4 -.lcomm cv_factor_nsecs_shift 1 +.lcomm cv_factor 8 +.lcomm cv_factor_nsecs 8 .text FUNCTION(__x86_setup_system_time): - movl 4(%esp), %eax - movl %eax, cv_factor - movl 8(%esp), %eax - movl %eax, cv_factor_nsecs - movb 12(%esp), %al - movb %al, cv_factor_nsecs_shift + movq %rdi, cv_factor + movq %rsi, cv_factor_nsecs ret FUNCTION_END(__x86_setup_system_time) /* int64 system_time(); */ FUNCTION(system_time): - pushl %ebx - pushl %ecx - movl cv_factor, %ebx + movq cv_factor, %rcx - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ + // Load 64-bit TSC into %eax (low), %edx (high). + rdtsc - movl %edx, %ecx /* save high half */ - mull %ebx /* truncate %eax, but keep %edx */ - movl %ecx, %eax - movl %edx, %ecx /* save high half of low */ - mull %ebx /*, %eax*/ - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - subl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx - popl %ecx - popl %ebx + // Convert into a single 64-bit value. + shl $32, %rdx + orq %rdx, %rax + + // Multiply by conversion factor, result in %rax (low), %rdx (high). + mulq %rcx + + // Shift the result right by 32 bits. + shr $32, %rax + shl $32, %rdx + orq %rdx, %rax ret FUNCTION_END(system_time) /* int64 system_time_nsecs(); */ FUNCTION(system_time_nsecs): - testb $0, cv_factor_nsecs_shift - jne 1f + // Same algorithm as system_time(), just with a different factor. + movq cv_factor_nsecs, %rcx - /* same algorithm as system_time(), just with a different factor */ + // Load 64-bit TSC into %eax (low), %edx (high). + rdtsc - pushl %ebx - pushl %ecx - movl cv_factor_nsecs, %ebx + // Convert into a single 64-bit value. + shl $32, %rdx + orq %rdx, %rax - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ + // Multiply by conversion factor, result in %rax (low), %rdx (high). + mulq %rcx - movl %edx, %ecx /* save high half */ - mull %ebx /* truncate %eax, but keep %edx */ - movl %ecx, %eax - movl %edx, %ecx /* save high half of low */ - mull %ebx /*, %eax*/ - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - subl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx - popl %ecx - popl %ebx - ret - -1: - /* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */ - - pushl %ebx - pushl %ecx - pushl %esi - movl cv_factor_nsecs, %ebx - - /* load 64-bit factor into %eax (low), %edx (high) */ - rdtsc /* time in %edx,%eax */ - - /* save high half */ - movl %edx, %ecx - - /* multiply low half by conversion factor */ - mull %ebx - - /* save result */ - movl %eax, %esi /* low half -> %esi */ - movl %ecx, %eax - movl %edx, %ecx /* high half -> %ecx */ - - /* multiply high half by conversion factor */ - mull %ebx - - /* now compute [%edx, %eax] + [%ecx], propagating carry */ - xorl %ebx, %ebx /* need zero to propagate carry */ - addl %ecx, %eax - adc %ebx, %edx - - /* shift the result left 16 bit */ - shl $16, %edx - movl %eax, %ebx - shr $16, %ebx - orw %bx, %dx - shl $16, %eax - - /* add the high 16 bit of the low half of the low product */ - shr $16, %esi - orw %si, %ax - - popl %esi - popl %ecx - popl %ebx + // Shift the result right by 32 bits. + shr $32, %rax + shl $32, %rdx + orq %rdx, %rax ret FUNCTION_END(system_time_nsecs) -#endif From cc248cf2b37b96f8f86d652e0121be105b23d192 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 8 Jul 2012 11:56:06 +0100 Subject: [PATCH 081/273] A couple of bug fixes. * mmu_get_virtual_mapping() should check that the page directory entry is present rather than assuming there's a page table there. This was resulting in some invalid mappings being created in the 64-bit virtual address space. * arch_vm_init_end() should clear from KERNEL_LOAD_BASE to virtual_end, not from KERNEL_BASE. On x86_64 this was causing it to loop through ~512GB of address space, which obviously was taking quite a while. --- src/system/boot/platform/bios_ia32/mmu.cpp | 17 +++++++++-------- src/system/kernel/arch/x86/arch_cpu.cpp | 3 --- src/system/kernel/arch/x86/arch_vm.cpp | 4 ++-- .../paging/64bit/X86VMTranslationMap64Bit.cpp | 3 ++- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 1046b70116..05167e7c3c 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -512,17 +512,18 @@ mmu_get_virtual_mapping(addr_t virtualAddress, addr_t *_physicalAddress) (void *)virtualAddress); } - uint32 *pageTable = (uint32 *)(sPageDirectory[virtualAddress - / (B_PAGE_SIZE * 1024)] & 0xfffff000); + uint32 dirEntry = sPageDirectory[virtualAddress / (B_PAGE_SIZE * 1024)]; + if ((dirEntry & (1 << 0)) == 0) + return false; + + uint32 *pageTable = (uint32 *)(dirEntry & 0xfffff000); uint32 tableEntry = pageTable[(virtualAddress % (B_PAGE_SIZE * 1024)) / B_PAGE_SIZE]; - - if ((tableEntry & (1<<0)) != 0) { - *_physicalAddress = tableEntry & 0xFFFFF000; - return true; - } else { + if ((tableEntry & (1 << 0)) == 0) return false; - } + + *_physicalAddress = tableEntry & 0xFFFFF000; + return true; } diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 6a7a2069b1..2edd3c392d 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -897,10 +897,7 @@ arch_cpu_init_post_vm(kernel_args* args) } #endif - // TODO x86_64 -#ifndef __x86_64 if (!apic_available()) -#endif x86_init_fpu(); // else fpu gets set up in smp code diff --git a/src/system/kernel/arch/x86/arch_vm.cpp b/src/system/kernel/arch/x86/arch_vm.cpp index 8fe04923de..f5948e13a2 100644 --- a/src/system/kernel/arch/x86/arch_vm.cpp +++ b/src/system/kernel/arch/x86/arch_vm.cpp @@ -672,8 +672,8 @@ arch_vm_init_end(kernel_args *args) TRACE(("arch_vm_init_endvm: entry\n")); // throw away anything in the kernel_args.pgtable[] that's not yet mapped - vm_free_unused_boot_loader_range(KERNEL_BASE, - args->arch_args.virtual_end - KERNEL_BASE); + vm_free_unused_boot_loader_range(KERNEL_LOAD_BASE, + args->arch_args.virtual_end - KERNEL_LOAD_BASE); return B_OK; } diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp index 24e85c2cde..2217bfe16b 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -539,7 +539,8 @@ X86VMTranslationMap64Bit::Query(addr_t virtualAddress, | ((entry & X86_64_PTE_PRESENT) != 0 ? PAGE_PRESENT : 0); TRACE("X86VMTranslationMap64Bit::Query(%#" B_PRIxADDR ") -> %#" - B_PRIxPHYSADDR ":\n", virtualAddress, *_physicalAddress); + B_PRIxPHYSADDR " %#" B_PRIx32 " (pte: %p %#" B_PRIx64 ")\n", + virtualAddress, *_physicalAddress, *_flags, pte, entry); return B_OK; } From 93cba1da96275eb617fcdc581ec4522e0b107adf Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 8 Jul 2012 15:03:23 +0100 Subject: [PATCH 082/273] Fixed a bug resulting from a mistake in the boot 64-bit paging setup. This was an interesting bug to find. Was getting spurious triple faults in the slab allocator. The problem was that the boot paging setup code was mapping all page tables it created into the virtual address space, but in the kernel no areas were being created to cover them, so during arch_vm_init_end() the pages for them ended up being freed and then overwritten later on. Fixed by unmapping page tables after populating them in long_mmu_init(). --- src/system/boot/platform/bios_ia32/long.cpp | 28 ++++++++++++------- src/system/kernel/arch/x86/64/stubs.cpp | 2 +- .../x86/paging/64bit/X86PagingMethod64Bit.cpp | 8 +++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 16fd1ae0f1..28137d48eb 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -106,6 +106,13 @@ long_mmu_init() memset(pml4, 0, B_PAGE_SIZE); gKernelArgs.arch_args.vir_pgdir = fix_address((uint64)(addr_t)pml4); + // Store the virtual memory usage information. + gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64BIT; + gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage(); + gKernelArgs.num_virtual_allocated_ranges = 1; + gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64BIT + + gKernelArgs.virtual_allocated_range[0].size, 0x200000); + // Find the highest physical memory address. We map all physical memory // into the kernel address space, so we want to make sure we map everything // we have available. @@ -144,8 +151,12 @@ long_mmu_init() for (uint64 j = 0; j < 0x40000000; j += 0x200000) { pageDir[j / 0x200000] = (i + j) | kLargePageMappingFlags; } + + mmu_free(pageDir, B_PAGE_SIZE); } + mmu_free(pdpt, B_PAGE_SIZE); + // Allocate tables for the kernel mappings. pdpt = (uint64*)mmu_allocate_page(&physicalAddress); @@ -156,23 +167,18 @@ long_mmu_init() memset(pageDir, 0, B_PAGE_SIZE); pdpt[510] = physicalAddress | kTableMappingFlags; - // Store the virtual memory usage information. - gKernelArgs.virtual_allocated_range[0].start = KERNEL_LOAD_BASE_64BIT; - gKernelArgs.virtual_allocated_range[0].size = mmu_get_virtual_usage(); - gKernelArgs.num_virtual_allocated_ranges = 1; - // We can now allocate page tables and duplicate the mappings across from // the 32-bit address space to them. pageTable = NULL; for (uint32 i = 0; i < gKernelArgs.virtual_allocated_range[0].size / B_PAGE_SIZE; i++) { if ((i % 512) == 0) { + if (pageTable) + mmu_free(pageTable, B_PAGE_SIZE); + pageTable = (uint64*)mmu_allocate_page(&physicalAddress); memset(pageTable, 0, B_PAGE_SIZE); pageDir[i / 512] = physicalAddress | kTableMappingFlags; - - // Just performed another virtual allocation, account for it. - gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE; } // Get the physical address to map. @@ -183,8 +189,10 @@ long_mmu_init() pageTable[i % 512] = physicalAddress | kPageMappingFlags; } - gKernelArgs.arch_args.virtual_end = ROUNDUP(KERNEL_LOAD_BASE_64BIT - + gKernelArgs.virtual_allocated_range[0].size, 0x200000); + if (pageTable) + mmu_free(pageTable, B_PAGE_SIZE); + mmu_free(pageDir, B_PAGE_SIZE); + mmu_free(pdpt, B_PAGE_SIZE); // Sort the address ranges. sort_address_ranges(gKernelArgs.physical_memory_range, diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 041e17f525..a803b1ce19 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -324,7 +324,7 @@ arch_system_info_init(struct kernel_args *args) status_t arch_thread_init(struct kernel_args *args) { - return B_OK; + return B_ERROR; } diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp index 4c622548d3..a834cd264c 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp @@ -197,7 +197,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, vm_page_reservation* reservation, TranslationMapPhysicalPageMapper* pageMapper, int32& mapCount) { - TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(%#" B_PRIxADDR ", " + TRACE("X86PagingMethod64Bit::PageTableForAddress(%#" B_PRIxADDR ", " "%d)\n", virtualAddress, allocateTables); // Get the PDPT. @@ -215,7 +215,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, phys_addr_t physicalPDPT = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; - TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating PDPT " + TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating PDPT " "for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, physicalPDPT); @@ -245,7 +245,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, phys_addr_t physicalPageDir = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; - TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page " + TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating page " "directory for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, physicalPageDir); @@ -275,7 +275,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, phys_addr_t physicalPageTable = (phys_addr_t)page->physical_page_number * B_PAGE_SIZE; - TRACE("X86PagingMethod64Bit::PageTableEntryForAddress(): creating page " + TRACE("X86PagingMethod64Bit::PageTableForAddress(): creating page " "table for va %#" B_PRIxADDR " at %#" B_PRIxPHYSADDR "\n", virtualAddress, physicalPageTable); From bc3093488f72315d8474d45b3dfe34cdc15ef4d6 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 09:03:11 +0100 Subject: [PATCH 083/273] Changes suggested by Ingo: style fix, and a system_time optimization. --- src/system/boot/platform/bios_ia32/mmu.cpp | 2 +- .../libroot/os/arch/x86_64/system_time_asm.S | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 05167e7c3c..4eef5defa5 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -522,7 +522,7 @@ mmu_get_virtual_mapping(addr_t virtualAddress, addr_t *_physicalAddress) if ((tableEntry & (1 << 0)) == 0) return false; - *_physicalAddress = tableEntry & 0xFFFFF000; + *_physicalAddress = tableEntry & 0xfffff000; return true; } diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S index f63bdf35ba..135b54a4c3 100644 --- a/src/system/libroot/os/arch/x86_64/system_time_asm.S +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -28,7 +28,10 @@ FUNCTION_END(__x86_setup_system_time) /* int64 system_time(); */ FUNCTION(system_time): + // (rdtsc * cv_factor) >> 32. + movq cv_factor, %rcx + shl $32, %rcx // Load 64-bit TSC into %eax (low), %edx (high). rdtsc @@ -40,17 +43,19 @@ FUNCTION(system_time): // Multiply by conversion factor, result in %rax (low), %rdx (high). mulq %rcx - // Shift the result right by 32 bits. - shr $32, %rax - shl $32, %rdx - orq %rdx, %rax + // Conversion factor preshifted by 32, whole result in high. + movq %rdx, %rax ret FUNCTION_END(system_time) /* int64 system_time_nsecs(); */ FUNCTION(system_time_nsecs): - // Same algorithm as system_time(), just with a different factor. + // Same algorithm as system_time(), but with a different factor. + // (rdtsc * cv_factor_nsecs) >> 32. + // Cannot pre-shift the factor here, otherwise we may lose the upper + // 32 bits. + movq cv_factor_nsecs, %rcx // Load 64-bit TSC into %eax (low), %edx (high). From 3b802628b8e2aa14eb4c674d0a8cf900f522baa1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 11:11:38 +0100 Subject: [PATCH 084/273] Support ELF64 in the kernel. This has been done by adding typedefs in elf_common.h to the correct ELF structures for the architecture, and changing all Elf32_* uses to those types. I don't know whether image loading works as I cannot test it yet, there may be some 64-bit safety issues around. However, symbol lookup for the kernel is working correctly. --- headers/private/kernel/arch/elf.h | 13 +- headers/private/kernel/boot/elf.h | 8 + headers/private/kernel/elf_priv.h | 85 ++--- .../private/runtime_loader/runtime_loader.h | 6 +- headers/private/system/elf32.h | 6 + headers/private/system/elf64.h | 8 + headers/private/system/elf_common.h | 35 +++ src/system/kernel/arch/x86/64/stubs.cpp | 66 ---- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_elf.cpp | 34 +- src/system/kernel/elf.cpp | 293 +++++++++--------- src/system/kernel/vm/vm.cpp | 8 +- 12 files changed, 287 insertions(+), 277 deletions(-) diff --git a/headers/private/kernel/arch/elf.h b/headers/private/kernel/arch/elf.h index bc8d44f776..d2dc5d8588 100644 --- a/headers/private/kernel/arch/elf.h +++ b/headers/private/kernel/arch/elf.h @@ -5,23 +5,28 @@ #ifndef _KERNEL_ARCH_ELF_H #define _KERNEL_ARCH_ELF_H -struct Elf32_Rel; -struct Elf32_Rela; + +#include + + struct elf_image_info; + #ifdef __cplusplus extern "C" { #endif extern int arch_elf_relocate_rel(struct elf_image_info *image, - struct elf_image_info *resolve_image, struct Elf32_Rel *rel, int rel_len); + struct elf_image_info *resolve_image, elf_rel *rel, int rel_len); extern int arch_elf_relocate_rela(struct elf_image_info *image, - struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len); + struct elf_image_info *resolve_image, elf_rela *rel, int rel_len); #ifdef __cplusplus } #endif + #include + #endif /* _KERNEL_ARCH_ELF_H */ diff --git a/headers/private/kernel/boot/elf.h b/headers/private/kernel/boot/elf.h index d2cfe06195..2f38836472 100644 --- a/headers/private/kernel/boot/elf.h +++ b/headers/private/kernel/boot/elf.h @@ -77,6 +77,14 @@ struct preloaded_elf64_image : public preloaded_image { FixedWidthPointer debug_symbols; } _PACKED; + +#if B_HAIKU_64_BIT +typedef preloaded_elf64_image preloaded_elf_image; +#else +typedef preloaded_elf32_image preloaded_elf_image; +#endif + + #ifdef _BOOT_MODE extern status_t boot_elf_resolve_symbol(preloaded_elf32_image* image, struct Elf32_Sym* symbol, Elf32_Addr* symbolAddress); diff --git a/headers/private/kernel/elf_priv.h b/headers/private/kernel/elf_priv.h index fd386c49d4..0b6341fbaf 100644 --- a/headers/private/kernel/elf_priv.h +++ b/headers/private/kernel/elf_priv.h @@ -25,60 +25,67 @@ typedef struct elf_region { } elf_region; struct elf_image_info { - struct elf_image_info *next; // next image in the hash - char *name; - image_id id; - int32 ref_count; - struct vnode *vnode; - elf_region text_region; - elf_region data_region; - addr_t dynamic_section; // pointer to the dynamic section - struct elf_linked_image *linked_images; + struct elf_image_info* next; // next image in the hash + char* name; + image_id id; + int32 ref_count; + struct vnode* vnode; + elf_region text_region; + elf_region data_region; + addr_t dynamic_section; // pointer to the dynamic section + struct elf_linked_image* linked_images; - bool symbolic; + bool symbolic; - struct Elf32_Ehdr *elf_header; + elf_ehdr* elf_header; // pointer to symbol participation data structures - char *needed; - uint32 *symhash; - struct Elf32_Sym *syms; - char *strtab; - struct Elf32_Rel *rel; - int rel_len; - struct Elf32_Rela *rela; - int rela_len; - struct Elf32_Rel *pltrel; - int pltrel_len; - int pltrel_type; + char* needed; + uint32* symhash; + elf_sym* syms; + char* strtab; + elf_rel* rel; + int rel_len; + elf_rela* rela; + int rela_len; + elf_rel* pltrel; + int pltrel_len; + int pltrel_type; - struct Elf32_Sym *debug_symbols; - uint32 num_debug_symbols; - const char *debug_string_table; + elf_sym* debug_symbols; + uint32 num_debug_symbols; + const char* debug_string_table; // versioning related structures - uint32 num_version_definitions; - struct Elf32_Verdef *version_definitions; - uint32 num_needed_versions; - struct Elf32_Verneed *needed_versions; - Elf32_Versym *symbol_versions; - struct elf_version_info *versions; - uint32 num_versions; + uint32 num_version_definitions; + elf_verdef* version_definitions; + uint32 num_needed_versions; + elf_verneed* needed_versions; + elf_versym* symbol_versions; + struct elf_version_info* versions; + uint32 num_versions; }; -#define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) +#define STRING(image, offset) ((char*)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) #define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) -#define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) -#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) +#define HASHBUCKETS(image) ((unsigned int*)&(image)->symhash[2]) +#define HASHCHAINS(image) ((unsigned int*)&(image)->symhash[2+HASHTABSIZE(image)]) + -extern #ifdef __cplusplus -"C" +extern "C" { #endif -status_t elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, - struct elf_image_info *shared_image, addr_t *sym_addr); + +extern status_t elf_resolve_symbol(struct elf_image_info* image, + elf_sym* symbol, struct elf_image_info* sharedImage, + addr_t* _symbolAddress); + +#ifdef __cplusplus +} +#endif + #endif /* _KERNEL_ELF_PRIV_H */ diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index ddccda1209..4cdac83290 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -152,12 +152,12 @@ typedef struct image_queue_t { #define IMAGE_FLAG_RTLD_MASK 0x03 // RTLD_{LAZY,NOW} | RTLD_{LOCAL,GLOBAL} -#define STRING(image, offset) ((char *)(&(image)->strtab[(offset)])) +#define STRING(image, offset) ((char*)(&(image)->strtab[(offset)])) #define SYMNAME(image, sym) STRING(image, (sym)->st_name) #define SYMBOL(image, num) (&(image)->syms[num]) #define HASHTABSIZE(image) ((image)->symhash[0]) -#define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2]) -#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)]) +#define HASHBUCKETS(image) ((unsigned int*)&(image)->symhash[2]) +#define HASHCHAINS(image) ((unsigned int*)&(image)->symhash[2+HASHTABSIZE(image)]) // The name of the area the runtime loader creates for debugging purposes. diff --git a/headers/private/system/elf32.h b/headers/private/system/elf32.h index d9287075df..c1bf7e245d 100644 --- a/headers/private/system/elf32.h +++ b/headers/private/system/elf32.h @@ -89,6 +89,7 @@ struct Elf32_Sym { #ifdef __cplusplus uint8 Bind() const; uint8 Type() const; + void SetInfo(uint8 bind, uint8 type); #endif }; @@ -218,6 +219,11 @@ Elf32_Sym::Type() const return ELF32_ST_TYPE(st_info); } +inline void +Elf32_Sym::SetInfo(uint8 bind, uint8 type) +{ + st_info = ELF32_ST_INFO(bind, type); +} inline uint8 Elf32_Rel::SymbolIndex() const diff --git a/headers/private/system/elf64.h b/headers/private/system/elf64.h index dc354060a1..3efd48b32a 100644 --- a/headers/private/system/elf64.h +++ b/headers/private/system/elf64.h @@ -91,6 +91,7 @@ struct Elf64_Sym { #ifdef __cplusplus uint8 Bind() const; uint8 Type() const; + void SetInfo(uint8 bind, uint8 type); #endif }; @@ -221,6 +222,13 @@ Elf64_Sym::Type() const } +inline void +Elf64_Sym::SetInfo(uint8 bind, uint8 type) +{ + st_info = ELF64_ST_INFO(bind, type); +} + + inline uint8 Elf64_Rel::SymbolIndex() const { diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h index 61eb43f67e..edfd744b09 100644 --- a/headers/private/system/elf_common.h +++ b/headers/private/system/elf_common.h @@ -263,4 +263,39 @@ #define VER_FLG_WEAK 0x2 /* weak version identifier */ +// Determine the correct ELF types to use for the architecture + +#if B_HAIKU_64_BIT +# define _ELF_TYPE(type) Elf64_##type +#else +# define _ELF_TYPE(type) Elf32_##type +#endif +#define DEFINE_ELF_TYPE(type, name) \ + struct _ELF_TYPE(type); \ + typedef _ELF_TYPE(type) name + +DEFINE_ELF_TYPE(Ehdr, elf_ehdr); +DEFINE_ELF_TYPE(Phdr, elf_phdr); +DEFINE_ELF_TYPE(Shdr, elf_shdr); +DEFINE_ELF_TYPE(Sym, elf_sym); +DEFINE_ELF_TYPE(Dyn, elf_dyn); +DEFINE_ELF_TYPE(Rel, elf_rel); +DEFINE_ELF_TYPE(Rela, elf_rela); +DEFINE_ELF_TYPE(Verdef, elf_verdef); +DEFINE_ELF_TYPE(Verdaux, elf_verdaux); +DEFINE_ELF_TYPE(Verneed, elf_verneed); +DEFINE_ELF_TYPE(Vernaux, elf_vernaux); + +#undef DEFINE_ELF_TYPE +#undef _ELF_TYPE + +typedef uint16 elf_versym; + +#if B_HAIKU_64_BIT +# define ELF_CLASS ELFCLASS64 +#else +# define ELF_CLASS ELFCLASS32 +#endif + + #endif /* _ELF_COMMON_H_ */ diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index a803b1ce19..0e82a298f9 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -510,72 +510,6 @@ x86_init_user_debug() } -// Currently got generic elf.cpp #ifdef'd out for x86_64, define stub versions here. - -status_t -elf_load_user_image(const char *path, Team *team, int flags, addr_t *_entry) -{ - return B_ERROR; -} - -image_id -load_kernel_add_on(const char *path) -{ - return 0; -} - -status_t -unload_kernel_add_on(image_id id) -{ - return B_ERROR; -} - -status_t -elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, - const char **_symbolName, const char **_imageName, bool *_exactMatch) -{ - return B_ERROR; -} - -addr_t -elf_debug_lookup_symbol(const char* searchName) -{ - return 0; -} - -struct elf_image_info * -elf_get_kernel_image() -{ - return NULL; -} - -image_id -elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, - addr_t data, size_t dataSize) -{ - return B_ERROR; -} - -status_t -elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, - size_t size, int32 type) -{ - return B_ERROR; -} - -status_t -elf_init(struct kernel_args *args) -{ - return B_OK; -} - -status_t -get_image_symbol(image_id image, const char *name, int32 symbolType, - void **_symbolLocation) -{ - return B_OK; -} - status_t _user_read_kernel_image_symbols(image_id id, struct Elf32_Sym* symbolTable, int32* _symbolCount, char* stringTable, size_t* _stringTableSize, diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 70d101314b..ad27ff118e 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -46,7 +46,6 @@ if $(TARGET_ARCH) = x86_64 { arch_commpage.cpp arch_debug.cpp - arch_elf.cpp arch_real_time_clock.cpp arch_smp.cpp arch_thread.cpp @@ -81,6 +80,7 @@ if $(TARGET_ARCH) = x86_64 { local archGenericSources = arch_cpu.cpp arch_debug_console.cpp + arch_elf.cpp arch_int.cpp arch_platform.cpp arch_timer.cpp diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index 951a33dde5..fee26732a5 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -186,34 +186,33 @@ arch_elf_relocate_rela(struct elf_image_info *image, #endif // !__x86_64__ || _BOOT_MODE -//#if defined(__x86_64__) || defined(_BOOT_MODE) -#ifdef _BOOT_MODE +#if defined(__x86_64__) || defined(_BOOT_MODE) #ifdef _BOOT_MODE status_t boot_arch_elf_relocate_rel(preloaded_elf64_image* image, Elf64_Rel* rel, int relLength) -//#else -//int -//arch_elf_relocate_rel(struct elf_image_info *image, -// struct elf_image_info *resolveImage, struct Elf32_Rel *rel, int relLength) -//#endif +#else +int +arch_elf_relocate_rel(struct elf_image_info *image, + struct elf_image_info *resolveImage, Elf64_Rel *rel, int relLength) +#endif { dprintf("arch_elf_relocate_rel: not supported on x86_64\n"); return B_ERROR; } -//#ifdef _BOOT_MODE +#ifdef _BOOT_MODE status_t boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, int relLength) -//#else -//int -//arch_elf_relocate_rela(struct elf_image_info *image, -// struct elf_image_info *resolveImage, struct Elf32_Rela *rel, int relLength) -//#endif +#else +int +arch_elf_relocate_rela(struct elf_image_info *image, + struct elf_image_info *resolveImage, Elf64_Rela *rel, int relLength) +#endif { for (int i = 0; i < relLength / (int)sizeof(Elf64_Rela); i++) { int type = ELF64_R_TYPE(rel[i].r_info); @@ -225,11 +224,11 @@ boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, Elf64_Sym* symbol = SYMBOL(image, symIndex); status_t status; -//#ifdef _BOOT_MODE +#ifdef _BOOT_MODE status = boot_elf_resolve_symbol(image, symbol, &symAddr); -//#else -// status = elf_resolve_symbol(image, symbol, resolveImage, &S); -//#endif +#else + status = elf_resolve_symbol(image, symbol, resolveImage, &symAddr); +#endif if (status < B_OK) return status; } @@ -269,7 +268,6 @@ boot_arch_elf_relocate_rela(preloaded_elf64_image* image, Elf64_Rela* rel, return B_OK; } -#endif #endif // __x86_64__ || _BOOT_MODE diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index f8c4e21f10..59e2928b2a 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -9,7 +9,6 @@ /*! Contains the ELF loader */ -#ifndef __x86_64__ #include @@ -67,8 +66,8 @@ static mutex sImageLoadMutex = MUTEX_INITIALIZER("kimages_load_lock"); static bool sInitialized = false; -static struct Elf32_Sym *elf_find_symbol(struct elf_image_info *image, - const char *name, const elf_version_info *version, bool lookupDefault); +static elf_sym *elf_find_symbol(struct elf_image_info *image, const char *name, + const elf_version_info *version, bool lookupDefault); /*! Calculates hash for an image using its ID */ @@ -76,7 +75,7 @@ static uint32 image_hash(void *_image, const void *_key, uint32 range) { struct elf_image_info *image = (struct elf_image_info *)_image; - image_id id = (image_id)_key; + image_id id = (image_id)(addr_t)_key; if (image != NULL) return image->id % range; @@ -90,7 +89,7 @@ static int image_compare(void *_image, const void *_key) { struct elf_image_info *image = (struct elf_image_info *)_image; - image_id id = (image_id)_key; + image_id id = (image_id)(addr_t)_key; return id - image->id; } @@ -124,11 +123,11 @@ register_elf_image(struct elf_image_info *image) // Haiku API version imageInfo.api_version = 0; - struct Elf32_Sym* symbol = elf_find_symbol(image, + elf_sym* symbol = elf_find_symbol(image, B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, NULL, true); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF && symbol->st_value > 0 - && ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT + && symbol->Type() == STT_OBJECT && symbol->st_size >= sizeof(uint32)) { addr_t symbolAddress = symbol->st_value + image->text_region.delta; if (symbolAddress >= image->text_region.start @@ -144,7 +143,7 @@ register_elf_image(struct elf_image_info *image) B_SHARED_OBJECT_HAIKU_ABI_VARIABLE_NAME, NULL, true); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF && symbol->st_value > 0 - && ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT + && symbol->Type() == STT_OBJECT && symbol->st_size >= sizeof(uint32)) { addr_t symbolAddress = symbol->st_value + image->text_region.delta; if (symbolAddress >= image->text_region.start @@ -234,7 +233,7 @@ dump_address_info(int argc, char **argv) static struct elf_image_info * find_image(image_id id) { - return (elf_image_info *)hash_lookup(sImagesHash, (void *)id); + return (elf_image_info *)hash_lookup(sImagesHash, (void *)(addr_t)id); } @@ -316,9 +315,9 @@ elf_hash(const char *name) static const char * -get_symbol_type_string(struct Elf32_Sym *symbol) +get_symbol_type_string(elf_sym *symbol) { - switch (ELF32_ST_TYPE(symbol->st_info)) { + switch (symbol->Type()) { case STT_FUNC: return "func"; case STT_OBJECT: @@ -332,9 +331,9 @@ get_symbol_type_string(struct Elf32_Sym *symbol) static const char * -get_symbol_bind_string(struct Elf32_Sym *symbol) +get_symbol_bind_string(elf_sym *symbol) { - switch (ELF32_ST_BIND(symbol->st_info)) { + switch (symbol->Bind()) { case STB_LOCAL: return "loc "; case STB_GLOBAL: @@ -368,7 +367,7 @@ dump_symbol(int argc, char **argv) if (image->num_debug_symbols > 0) { // search extended debug symbol table (contains static symbols) for (uint32 i = 0; i < image->num_debug_symbols; i++) { - struct Elf32_Sym *symbol = &image->debug_symbols[i]; + elf_sym *symbol = &image->debug_symbols[i]; const char *name = image->debug_string_table + symbol->st_name; if (symbol->st_value > 0 && strstr(name, pattern) != 0) { @@ -383,7 +382,7 @@ dump_symbol(int argc, char **argv) for (uint32 i = 0; i < HASHTABSIZE(image); i++) { for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; const char *name = SYMNAME(image, symbol); if (symbol->st_value > 0 && strstr(name, pattern) != 0) { @@ -415,7 +414,7 @@ dump_symbols(int argc, char **argv) // if the argument looks like a hex number, treat it as such if (argc > 1) { if (isdigit(argv[1][0])) { - uint32 num = strtoul(argv[1], NULL, 0); + addr_t num = strtoul(argv[1], NULL, 0); if (IS_KERNEL_ADDRESS(num)) { // find image at address @@ -430,12 +429,16 @@ dump_symbols(int argc, char **argv) } hash_close(sImagesHash, &iterator, false); - if (image == NULL) - kprintf("No image covers 0x%lx in the kernel!\n", num); + if (image == NULL) { + kprintf("No image covers %#" B_PRIxADDR " in the kernel!\n", + num); + } } else { image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); - if (image == NULL) - kprintf("image 0x%lx doesn't exist in the kernel!\n", num); + if (image == NULL) { + kprintf("image %#" B_PRIxADDR " doesn't exist in the " + "kernel!\n", num); + } } } else { // look for image by name @@ -460,13 +463,13 @@ dump_symbols(int argc, char **argv) // dump symbols - kprintf("Symbols of image %ld \"%s\":\nAddress Type Size Name\n", - image->id, image->name); + kprintf("Symbols of image %" B_PRId32 "\"%s\":\n" + "Address Type Size Name\n", image->id, image->name); if (image->num_debug_symbols > 0) { // search extended debug symbol table (contains static symbols) for (i = 0; i < image->num_debug_symbols; i++) { - struct Elf32_Sym *symbol = &image->debug_symbols[i]; + elf_sym *symbol = &image->debug_symbols[i]; if (symbol->st_value == 0 || symbol->st_size >= image->text_region.size + image->data_region.size) @@ -484,7 +487,7 @@ dump_symbols(int argc, char **argv) for (i = 0; i < HASHTABSIZE(image); i++) { for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; if (symbol->st_value == 0 || symbol->st_size >= image->text_region.size + image->data_region.size) @@ -506,9 +509,9 @@ dump_symbols(int argc, char **argv) static void dump_elf_region(struct elf_region *region, const char *name) { - kprintf(" %s.id %ld\n", name, region->id); - kprintf(" %s.start 0x%lx\n", name, region->start); - kprintf(" %s.size 0x%lx\n", name, region->size); + kprintf(" %s.id %" B_PRId32 "\n", name, region->id); + kprintf(" %s.start %#" B_PRIxADDR "\n", name, region->start); + kprintf(" %s.size %#" B_PRIxSIZE "\n", name, region->size); kprintf(" %s.delta %ld\n", name, region->delta); } @@ -518,22 +521,22 @@ dump_image_info(struct elf_image_info *image) { kprintf("elf_image_info at %p:\n", image); kprintf(" next %p\n", image->next); - kprintf(" id %ld\n", image->id); + kprintf(" id %" B_PRId32 "\n", image->id); dump_elf_region(&image->text_region, "text"); dump_elf_region(&image->data_region, "data"); - kprintf(" dynamic_section 0x%lx\n", image->dynamic_section); + kprintf(" dynamic_section %#" B_PRIxADDR "\n", image->dynamic_section); kprintf(" needed %p\n", image->needed); kprintf(" symhash %p\n", image->symhash); kprintf(" syms %p\n", image->syms); kprintf(" strtab %p\n", image->strtab); kprintf(" rel %p\n", image->rel); - kprintf(" rel_len 0x%x\n", image->rel_len); + kprintf(" rel_len %#x\n", image->rel_len); kprintf(" rela %p\n", image->rela); - kprintf(" rela_len 0x%x\n", image->rela_len); + kprintf(" rela_len %#x\n", image->rela_len); kprintf(" pltrel %p\n", image->pltrel); - kprintf(" pltrel_len 0x%x\n", image->pltrel_len); + kprintf(" pltrel_len %#x\n", image->pltrel_len); - kprintf(" debug_symbols %p (%ld)\n", + kprintf(" debug_symbols %p (%" B_PRIu32 ")\n", image->debug_symbols, image->num_debug_symbols); } @@ -546,16 +549,17 @@ dump_image(int argc, char **argv) // if the argument looks like a hex number, treat it as such if (argc > 1) { - uint32 num = strtoul(argv[1], NULL, 0); + addr_t num = strtoul(argv[1], NULL, 0); if (IS_KERNEL_ADDRESS(num)) { // semi-hack dump_image_info((struct elf_image_info *)num); } else { image = (elf_image_info *)hash_lookup(sImagesHash, (void *)num); - if (image == NULL) - kprintf("image 0x%lx doesn't exist in the kernel!\n", num); - else + if (image == NULL) { + kprintf("image %#" B_PRIxADDR " doesn't exist in the kernel!\n", + num); + } else dump_image_info(image); } return 0; @@ -567,7 +571,7 @@ dump_image(int argc, char **argv) while ((image = (elf_image_info *)hash_next(sImagesHash, &iterator)) != NULL) { - kprintf("%p (%ld) %s\n", image, image->id, image->name); + kprintf("%p (%" B_PRId32 ") %s\n", image, image->id, image->name); } hash_close(sImagesHash, &iterator, false); @@ -578,7 +582,7 @@ dump_image(int argc, char **argv) // Currently unused #if 0 static -void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym) +void dump_symbol(struct elf_image_info *image, elf_sym *sym) { kprintf("symbol at %p, in image %p\n", sym, image); @@ -593,25 +597,24 @@ void dump_symbol(struct elf_image_info *image, struct Elf32_Sym *sym) #endif -static struct Elf32_Sym * +static elf_sym * elf_find_symbol(struct elf_image_info *image, const char *name, const elf_version_info *lookupVersion, bool lookupDefault) { if (image->dynamic_section == 0 || HASHTABSIZE(image) == 0) return NULL; - Elf32_Sym* versionedSymbol = NULL; + elf_sym* versionedSymbol = NULL; uint32 versionedSymbolCount = 0; uint32 hash = elf_hash(name) % HASHTABSIZE(image); for (uint32 i = HASHBUCKETS(image)[hash]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { - Elf32_Sym* symbol = &image->syms[i]; + elf_sym* symbol = &image->syms[i]; // consider only symbols with the right name and binding if (symbol->st_shndx == SHN_UNDEF - || ((ELF32_ST_BIND(symbol->st_info) != STB_GLOBAL) - && (ELF32_ST_BIND(symbol->st_info) != STB_WEAK)) + || ((symbol->Bind() != STB_GLOBAL) && (symbol->Bind() != STB_WEAK)) || strcmp(SYMNAME(image, symbol), name) != 0) { continue; } @@ -705,7 +708,7 @@ elf_find_symbol(struct elf_image_info *image, const char *name, static status_t elf_parse_dynamic_section(struct elf_image_info *image) { - struct Elf32_Dyn *d; + elf_dyn *d; int32 neededOffset = -1; TRACE(("top of elf_parse_dynamic_section\n")); @@ -714,7 +717,7 @@ elf_parse_dynamic_section(struct elf_image_info *image) image->syms = 0; image->strtab = 0; - d = (struct Elf32_Dyn *)image->dynamic_section; + d = (elf_dyn *)image->dynamic_section; if (!d) return B_ERROR; @@ -732,25 +735,25 @@ elf_parse_dynamic_section(struct elf_image_info *image) + image->text_region.delta); break; case DT_SYMTAB: - image->syms = (struct Elf32_Sym *)(d[i].d_un.d_ptr + image->syms = (elf_sym *)(d[i].d_un.d_ptr + image->text_region.delta); break; case DT_REL: - image->rel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->rel = (elf_rel *)(d[i].d_un.d_ptr + image->text_region.delta); break; case DT_RELSZ: image->rel_len = d[i].d_un.d_val; break; case DT_RELA: - image->rela = (struct Elf32_Rela *)(d[i].d_un.d_ptr + image->rela = (elf_rela *)(d[i].d_un.d_ptr + image->text_region.delta); break; case DT_RELASZ: image->rela_len = d[i].d_un.d_val; break; case DT_JMPREL: - image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->pltrel = (elf_rel *)(d[i].d_un.d_ptr + image->text_region.delta); break; case DT_PLTRELSZ: @@ -760,18 +763,18 @@ elf_parse_dynamic_section(struct elf_image_info *image) image->pltrel_type = d[i].d_un.d_val; break; case DT_VERSYM: - image->symbol_versions = (Elf32_Versym*) + image->symbol_versions = (elf_versym*) (d[i].d_un.d_ptr + image->text_region.delta); break; case DT_VERDEF: - image->version_definitions = (Elf32_Verdef*) + image->version_definitions = (elf_verdef*) (d[i].d_un.d_ptr + image->text_region.delta); break; case DT_VERDEFNUM: image->num_version_definitions = d[i].d_un.d_val; break; case DT_VERNEED: - image->needed_versions = (Elf32_Verneed*) + image->needed_versions = (elf_verneed*) (d[i].d_un.d_ptr + image->text_region.delta); break; case DT_VERNEEDNUM: @@ -820,7 +823,7 @@ assert_defined_image_version(elf_image_info* dependentImage, } // iterate through the defined versions to find the given one - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { uint32 versionIndex = VER_NDX(definition->vd_ndx); elf_version_info& info = image->versions[versionIndex]; @@ -830,7 +833,7 @@ assert_defined_image_version(elf_image_info* dependentImage, return B_OK; } - definition = (Elf32_Verdef*) + definition = (elf_verdef*) ((uint8*)definition + definition->vd_next); } @@ -854,7 +857,7 @@ init_image_version_infos(elf_image_info* image) uint32 maxIndex = 0; if (image->version_definitions != NULL) { - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { if (definition->vd_version != 1) { dprintf("Unsupported version definition revision: %u\n", @@ -866,13 +869,13 @@ init_image_version_infos(elf_image_info* image) if (versionIndex > maxIndex) maxIndex = versionIndex; - definition = (Elf32_Verdef*) + definition = (elf_verdef*) ((uint8*)definition + definition->vd_next); } } if (image->needed_versions != NULL) { - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { if (needed->vn_version != 1) { dprintf("Unsupported version needed revision: %u\n", @@ -880,17 +883,17 @@ init_image_version_infos(elf_image_info* image) return B_BAD_VALUE; } - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); if (versionIndex > maxIndex) maxIndex = versionIndex; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } } @@ -910,12 +913,12 @@ init_image_version_infos(elf_image_info* image) // version definitions if (image->version_definitions != NULL) { - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { if (definition->vd_cnt > 0 && (definition->vd_flags & VER_FLG_BASE) == 0) { - Elf32_Verdaux* verdaux - = (Elf32_Verdaux*)((uint8*)definition + definition->vd_aux); + elf_verdaux* verdaux + = (elf_verdaux*)((uint8*)definition + definition->vd_aux); uint32 versionIndex = VER_NDX(definition->vd_ndx); elf_version_info& info = image->versions[versionIndex]; @@ -924,19 +927,19 @@ init_image_version_infos(elf_image_info* image) info.file_name = NULL; } - definition = (Elf32_Verdef*) + definition = (elf_verdef*) ((uint8*)definition + definition->vd_next); } } // needed versions if (image->needed_versions != NULL) { - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { const char* fileName = STRING(image, needed->vn_file); - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); elf_version_info& info = image->versions[versionIndex]; @@ -944,10 +947,10 @@ init_image_version_infos(elf_image_info* image) info.name = STRING(image, vernaux->vna_name); info.file_name = fileName; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } } @@ -961,12 +964,12 @@ check_needed_image_versions(elf_image_info* image) if (image->needed_versions == NULL) return B_OK; - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { elf_image_info* dependency = sKernelImage; - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); elf_version_info& info = image->versions[versionIndex]; @@ -976,10 +979,10 @@ check_needed_image_versions(elf_image_info* image) if (error != B_OK) return error; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } return B_OK; @@ -990,11 +993,11 @@ check_needed_image_versions(elf_image_info* image) Returns the resolved symbol's address in \a _symbolAddress. */ status_t -elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, +elf_resolve_symbol(struct elf_image_info *image, elf_sym *symbol, struct elf_image_info *sharedImage, addr_t *_symbolAddress) { // Local symbols references are always resolved to the given symbol. - if (ELF32_ST_BIND(symbol->st_info) == STB_LOCAL) { + if (symbol->Bind() == STB_LOCAL) { *_symbolAddress = symbol->st_value + image->text_region.delta; return B_OK; } @@ -1019,19 +1022,19 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, // find the symbol elf_image_info* foundImage = firstImage; - struct Elf32_Sym* foundSymbol = elf_find_symbol(firstImage, symbolName, - versionInfo, false); + elf_sym* foundSymbol = elf_find_symbol(firstImage, symbolName, versionInfo, + false); if (foundSymbol == NULL - || ELF32_ST_BIND(foundSymbol->st_info) == STB_WEAK) { + || foundSymbol->Bind() == STB_WEAK) { // Not found or found a weak definition -- try to resolve in the other // image. - Elf32_Sym* secondSymbol = elf_find_symbol(secondImage, symbolName, + elf_sym* secondSymbol = elf_find_symbol(secondImage, symbolName, versionInfo, false); // If we found a symbol -- take it in case we didn't have a symbol // before or the new symbol is not weak. if (secondSymbol != NULL && (foundSymbol == NULL - || ELF32_ST_BIND(secondSymbol->st_info) != STB_WEAK)) { + || secondSymbol->Bind() != STB_WEAK)) { foundImage = secondImage; foundSymbol = secondSymbol; } @@ -1039,7 +1042,7 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, if (foundSymbol == NULL) { // Weak undefined symbols get a value of 0, if unresolved. - if (ELF32_ST_BIND(symbol->st_info) == STB_WEAK) { + if (symbol->Bind() == STB_WEAK) { *_symbolAddress = 0; return B_OK; } @@ -1050,12 +1053,11 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *symbol, } // make sure they're the same type - if (ELF32_ST_TYPE(symbol->st_info) != ELF32_ST_TYPE(foundSymbol->st_info)) { + if (symbol->Type() != foundSymbol->Type()) { dprintf("elf_resolve_symbol: found symbol '%s' in image '%s' " "(requested by image '%s') but wrong type (%d vs. %d)\n", symbolName, foundImage->name, image->name, - ELF32_ST_TYPE(foundSymbol->st_info), - ELF32_ST_TYPE(symbol->st_info)); + foundSymbol->Type(), symbol->Type()); return B_MISSING_SYMBOL; } @@ -1074,8 +1076,7 @@ elf_relocate(struct elf_image_info *image) // deal with the rels first if (image->rel) { - TRACE(("total %i relocs\n", - image->rel_len / (int)sizeof(struct Elf32_Rel))); + TRACE(("total %i rel relocs\n", image->rel_len / (int)sizeof(elf_rel))); status = arch_elf_relocate_rel(image, sKernelImage, image->rel, image->rel_len); @@ -1084,21 +1085,25 @@ elf_relocate(struct elf_image_info *image) } if (image->pltrel) { - TRACE(("total %i plt-relocs\n", - image->pltrel_len / (int)sizeof(struct Elf32_Rel))); - if (image->pltrel_type == DT_REL) { + TRACE(("total %i plt-relocs\n", + image->pltrel_len / (int)sizeof(elf_rel))); status = arch_elf_relocate_rel(image, sKernelImage, image->pltrel, image->pltrel_len); } else { + TRACE(("total %i plt-relocs\n", + image->pltrel_len / (int)sizeof(elf_rela))); status = arch_elf_relocate_rela(image, sKernelImage, - (struct Elf32_Rela *)image->pltrel, image->pltrel_len); + (elf_rela *)image->pltrel, image->pltrel_len); } if (status < B_OK) return status; } if (image->rela) { + TRACE(("total %i rel relocs\n", + image->rela_len / (int)sizeof(elf_rela))); + status = arch_elf_relocate_rela(image, sKernelImage, image->rela, image->rela_len); if (status < B_OK) @@ -1110,18 +1115,18 @@ elf_relocate(struct elf_image_info *image) static int -verify_eheader(struct Elf32_Ehdr *elfHeader) +verify_eheader(elf_ehdr *elfHeader) { if (memcmp(elfHeader->e_ident, ELF_MAGIC, 4) != 0) return B_NOT_AN_EXECUTABLE; - if (elfHeader->e_ident[4] != ELFCLASS32) + if (elfHeader->e_ident[4] != ELF_CLASS) return B_NOT_AN_EXECUTABLE; if (elfHeader->e_phoff == 0) return B_NOT_AN_EXECUTABLE; - if (elfHeader->e_phentsize < sizeof(struct Elf32_Phdr)) + if (elfHeader->e_phentsize < sizeof(elf_phdr)) return B_NOT_AN_EXECUTABLE; return 0; @@ -1144,9 +1149,9 @@ unload_elf_image(struct elf_image_info *image) static status_t load_elf_symbol_table(int fd, struct elf_image_info *image) { - struct Elf32_Ehdr *elfHeader = image->elf_header; - struct Elf32_Sym *symbolTable = NULL; - struct Elf32_Shdr *stringHeader = NULL; + elf_ehdr *elfHeader = image->elf_header; + elf_sym *symbolTable = NULL; + elf_shdr *stringHeader = NULL; uint32 numSymbols = 0; char *stringTable; status_t status; @@ -1156,7 +1161,7 @@ load_elf_symbol_table(int fd, struct elf_image_info *image) // get section headers ssize_t size = elfHeader->e_shnum * elfHeader->e_shentsize; - struct Elf32_Shdr *sectionHeaders = (struct Elf32_Shdr *)malloc(size); + elf_shdr *sectionHeaders = (elf_shdr *)malloc(size); if (sectionHeaders == NULL) { dprintf("error allocating space for section headers\n"); return B_NO_MEMORY; @@ -1182,8 +1187,8 @@ load_elf_symbol_table(int fd, struct elf_image_info *image) } // read in symbol table - symbolTable - = (struct Elf32_Sym *)malloc(size = sectionHeaders[i].sh_size); + size = sectionHeaders[i].sh_size; + symbolTable = (elf_sym *)malloc(size); if (symbolTable == NULL) { status = B_NO_MEMORY; goto error1; @@ -1197,7 +1202,7 @@ load_elf_symbol_table(int fd, struct elf_image_info *image) goto error2; } - numSymbols = size / sizeof(struct Elf32_Sym); + numSymbols = size / sizeof(elf_sym); break; } } @@ -1245,7 +1250,7 @@ error1: static status_t -insert_preloaded_image(struct preloaded_elf32_image *preloadedImage, bool kernel) +insert_preloaded_image(preloaded_elf_image *preloadedImage, bool kernel) { status_t status; @@ -1290,9 +1295,9 @@ insert_preloaded_image(struct preloaded_elf32_image *preloadedImage, bool kernel // copy debug symbols to the kernel heap if (preloadedImage->debug_symbols != NULL) { - int32 debugSymbolsSize = sizeof(Elf32_Sym) + int32 debugSymbolsSize = sizeof(elf_sym) * preloadedImage->num_debug_symbols; - image->debug_symbols = (Elf32_Sym*)malloc(debugSymbolsSize); + image->debug_symbols = (elf_sym*)malloc(debugSymbolsSize); if (image->debug_symbols != NULL) { memcpy(image->debug_symbols, preloadedImage->debug_symbols, debugSymbolsSize); @@ -1333,6 +1338,8 @@ error1: // #pragma mark - userland symbol lookup +// TODO x86_64 +#ifndef __x86_64__ class UserSymbolLookup { public: static UserSymbolLookup& Default() @@ -1393,7 +1400,7 @@ public: const elf_region_t& textRegion = image.regions[0]; // search the image for the symbol - Elf32_Sym symbolFound; + elf_sym symbolFound; addr_t deltaFound = INT_MAX; bool exactMatch = false; @@ -1409,7 +1416,7 @@ public: for (uint32 j = bucket; j != STN_UNDEF; _Read(&hashChains[j], j) ? 0 : j = STN_UNDEF) { - Elf32_Sym symbol; + elf_sym symbol; if (!_Read(image.syms + j, symbol)) continue; @@ -1420,8 +1427,7 @@ public: // function and data symbols that have an st_value != 0 (0 // seems to be an indication for a symbol defined elsewhere // -- couldn't verify that in the specs though). - if ((ELF32_ST_TYPE(symbol.st_info) != STT_FUNC - && ELF32_ST_TYPE(symbol.st_info) != STT_OBJECT) + if ((symbol.Type() != STT_FUNC && symbol.Type() != STT_OBJECT) || symbol.st_value == 0 || symbol.st_value + symbol.st_size + textRegion.delta > textRegion.vmstart + textRegion.size) { @@ -1540,6 +1546,7 @@ UserSymbolLookup::_Read(const T* address, T& data) UserSymbolLookup UserSymbolLookup::sLookup; // doesn't need construction, but has an Init() method +#endif // #pragma mark - public kernel API @@ -1550,7 +1557,7 @@ get_image_symbol(image_id id, const char *name, int32 symbolClass, void **_symbol) { struct elf_image_info *image; - struct Elf32_Sym *symbol; + elf_sym *symbol; status_t status = B_OK; TRACE(("get_image_symbol(%s)\n", name)); @@ -1595,7 +1602,7 @@ elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) { struct elf_image_info *image; - struct Elf32_Sym *symbolFound = NULL; + elf_sym *symbolFound = NULL; const char *symbolName = NULL; addr_t deltaFound = INT_MAX; bool exactMatch = false; @@ -1625,7 +1632,7 @@ elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, TRACE((" searching debug symbols...\n")); for (i = 0; i < image->num_debug_symbols; i++) { - struct Elf32_Sym *symbol = &image->debug_symbols[i]; + elf_sym *symbol = &image->debug_symbols[i]; if (symbol->st_value == 0 || symbol->st_size >= image->text_region.size + image->data_region.size) @@ -1653,7 +1660,7 @@ elf_debug_lookup_symbol_address(addr_t address, addr_t *_baseAddress, for (i = 0; i < HASHTABSIZE(image); i++) { for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; if (symbol->st_value == 0 || symbol->st_size >= image->text_region.size @@ -1726,6 +1733,8 @@ elf_debug_lookup_user_symbol_address(Team* team, addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) { + // TODO x86_64 +#ifndef __x86_64__ if (team == NULL || team == team_get_kernel_team()) return B_BAD_VALUE; @@ -1736,6 +1745,9 @@ elf_debug_lookup_user_symbol_address(Team* team, addr_t address, return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName, _imageName, _exactMatch); +#else + return B_ENTRY_NOT_FOUND; +#endif } @@ -1754,7 +1766,7 @@ elf_debug_lookup_symbol(const char* searchName) if (image->num_debug_symbols > 0) { // search extended debug symbol table (contains static symbols) for (uint32 i = 0; i < image->num_debug_symbols; i++) { - struct Elf32_Sym *symbol = &image->debug_symbols[i]; + elf_sym *symbol = &image->debug_symbols[i]; const char *name = image->debug_string_table + symbol->st_name; if (symbol->st_value > 0 && !strcmp(name, searchName)) @@ -1765,7 +1777,7 @@ elf_debug_lookup_symbol(const char* searchName) for (uint32 i = 0; i < HASHTABSIZE(image); i++) { for (uint32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; const char *name = SYMNAME(image, symbol); if (symbol->st_value > 0 && !strcmp(name, searchName)) @@ -1784,7 +1796,7 @@ status_t elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info) { // find the symbol - Elf32_Sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false); + elf_sym* foundSymbol = elf_find_symbol(sKernelImage, name, NULL, false); if (foundSymbol == NULL) return B_MISSING_SYMBOL; @@ -1797,8 +1809,8 @@ elf_lookup_kernel_symbol(const char* name, elf_symbol_info* info) status_t elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) { - struct Elf32_Ehdr elfHeader; - struct Elf32_Phdr *programHeaders = NULL; + elf_ehdr elfHeader; + elf_phdr *programHeaders = NULL; char baseName[B_OS_NAME_LENGTH]; status_t status; ssize_t length; @@ -1835,7 +1847,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) // read program header - programHeaders = (struct Elf32_Phdr *)malloc( + programHeaders = (elf_phdr *)malloc( elfHeader.e_phnum * elfHeader.e_phentsize); if (programHeaders == NULL) { dprintf("error allocating space for program headers\n"); @@ -1917,10 +1929,10 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) // clean garbage brought by mmap (the region behind the file, // at least parts of it are the bss and have to be zeroed) - uint32 start = (uint32)regionAddress + addr_t start = (addr_t)regionAddress + (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz; - uint32 amount = fileUpperBound + size_t amount = fileUpperBound - (programHeaders[i].p_vaddr % B_PAGE_SIZE) - (programHeaders[i].p_filesz); memset((void *)start, 0, amount); @@ -2002,8 +2014,8 @@ error: image_id load_kernel_add_on(const char *path) { - struct Elf32_Phdr *programHeaders; - struct Elf32_Ehdr *elfHeader; + elf_phdr *programHeaders; + elf_ehdr *elfHeader; struct elf_image_info *image; const char *fileName; void *reservedAddress; @@ -2041,7 +2053,7 @@ load_kernel_add_on(const char *path) goto done; } - elfHeader = (struct Elf32_Ehdr *)malloc(sizeof(*elfHeader)); + elfHeader = (elf_ehdr *)malloc(sizeof(*elfHeader)); if (!elfHeader) { status = B_NO_MEMORY; goto error; @@ -2071,7 +2083,7 @@ load_kernel_add_on(const char *path) image->name = strdup(path); vnode = NULL; - programHeaders = (struct Elf32_Phdr *)malloc(elfHeader->e_phnum + programHeaders = (elf_phdr *)malloc(elfHeader->e_phnum * elfHeader->e_phentsize); if (programHeaders == NULL) { dprintf("%s: error allocating space for program headers\n", fileName); @@ -2148,7 +2160,7 @@ load_kernel_add_on(const char *path) image->dynamic_section = programHeaders[i].p_vaddr; continue; default: - dprintf("%s: unhandled pheader type 0x%lx\n", fileName, + dprintf("%s: unhandled pheader type %#" B_PRIx32 "\n", fileName, programHeaders[i].p_type); continue; } @@ -2185,7 +2197,7 @@ load_kernel_add_on(const char *path) textSectionWritable = programHeaders[i].IsReadWrite(); snprintf(regionName, B_OS_NAME_LENGTH, "%s_text", fileName); } else { - dprintf("%s: weird program header flags 0x%lx\n", fileName, + dprintf("%s: weird program header flags %#" B_PRIx32 "\n", fileName, programHeaders[i].p_flags); continue; } @@ -2213,7 +2225,8 @@ load_kernel_add_on(const char *path) programHeaders[i].p_filesz); if (length < B_OK) { status = length; - dprintf("%s: error reading in segment %ld\n", fileName, i); + dprintf("%s: error reading in segment %" B_PRId32 "\n", fileName, + i); goto error5; } } @@ -2355,7 +2368,7 @@ elf_create_memory_image(const char* imageName, addr_t text, size_t textSize, // allocate symbol and string tables -- we allocate an empty symbol table, // so that elf_debug_lookup_symbol_address() won't try the dynamic symbol // table, which we don't have. - Elf32_Sym* symbolTable = (Elf32_Sym*)malloc(0); + elf_sym* symbolTable = (elf_sym*)malloc(0); char* stringTable = (char*)malloc(1); MemoryDeleter symbolTableDeleter(symbolTable); MemoryDeleter stringTableDeleter(stringTable); @@ -2440,19 +2453,19 @@ elf_add_memory_image_symbol(image_id id, const char* name, addr_t address, // resize the symbol table int32 symbolCount = image->num_debug_symbols + 1; - Elf32_Sym* symbolTable = (Elf32_Sym*)realloc( - (Elf32_Sym*)image->debug_symbols, sizeof(Elf32_Sym) * symbolCount); + elf_sym* symbolTable = (elf_sym*)realloc( + (elf_sym*)image->debug_symbols, sizeof(elf_sym) * symbolCount); if (symbolTable == NULL) return B_NO_MEMORY; image->debug_symbols = symbolTable; // enter the symbol - Elf32_Sym& symbol = symbolTable[symbolCount - 1]; - uint32 symbolType = type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC; + elf_sym& symbol = symbolTable[symbolCount - 1]; + symbol.SetInfo(STB_GLOBAL, + type == B_SYMBOL_TYPE_DATA ? STT_OBJECT : STT_FUNC); symbol.st_name = stringIndex; symbol.st_value = address; symbol.st_size = size; - symbol.st_info = ELF32_ST_INFO(STB_GLOBAL, symbolType); symbol.st_other = 0; symbol.st_shndx = 0; image->num_debug_symbols++; @@ -2475,14 +2488,14 @@ elf_init(kernel_args *args) // Build a image structure for the kernel, which has already been loaded. // The preloaded_images were already prepared by the VM. image = args->kernel_image; - if (insert_preloaded_image(static_cast( - image), true) < B_OK) + if (insert_preloaded_image(static_cast(image), + true) < B_OK) panic("could not create kernel image.\n"); // Build image structures for all preloaded images. for (image = args->preloaded_images; image != NULL; image = image->next) - insert_preloaded_image(static_cast( - image), false); + insert_preloaded_image(static_cast(image), + false); add_debugger_command("ls", &dump_address_info, "lookup symbol for a particular address"); @@ -2501,6 +2514,8 @@ elf_init(kernel_args *args) // #pragma mark - +// TODO: x86_64 +#ifndef __x86_64__ /*! Reads the symbol and string table for the kernel image with the given ID. \a _symbolCount and \a _stringTableSize are both in- and output parameters. When called they call the size of the buffers given by \a symbolTable and diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 040893537f..21518a2d4d 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3543,13 +3543,7 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size) static void create_preloaded_image_areas(struct preloaded_image* _image) { - // TODO: Make this a typedef somewhere. Will be done when I implement - // ELF loading for x86_64. -#ifdef B_HAIKU_64_BIT - preloaded_elf64_image* image = static_cast(_image); -#else - preloaded_elf32_image* image = static_cast(_image); -#endif + preloaded_elf_image* image = static_cast(_image); char name[B_OS_NAME_LENGTH]; void* address; int32 length; From ee7aba5117fea8aa4d292fb9c105dc483c67a2e2 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 11:54:03 +0100 Subject: [PATCH 085/273] Print symbol information in a stack trace. --- src/system/kernel/arch/x86/64/stubs.cpp | 67 ++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 0e82a298f9..5f85b9aa2a 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -129,12 +130,66 @@ print_iframe(struct iframe* frame) } +static status_t +lookup_symbol(addr_t address, addr_t* _baseAddress, const char** _symbolName, + const char** _imageName, bool* _exactMatch) +{ + status_t status = B_ENTRY_NOT_FOUND; + + if (IS_KERNEL_ADDRESS(address)) { + status = elf_debug_lookup_symbol_address(address, _baseAddress, + _symbolName, _imageName, _exactMatch); + } + + return status; +} + + +static void +print_stack_frame(addr_t rip, addr_t rbp, addr_t nextRbp, int32 callIndex) +{ + const char* symbol; + const char* image; + addr_t baseAddress; + bool exactMatch; + status_t status; + addr_t diff; + + diff = nextRbp - rbp; + + // kernel space/user space switch + if (diff & (1L << 63)) + diff = 0; + + status = lookup_symbol(rip, &baseAddress, &symbol, &image, &exactMatch); + + kprintf("%2d %016lx (+%4ld) %016lx ", callIndex, rbp, diff, rip); + + if (status == B_OK) { + if (symbol != NULL) + kprintf("<%s>:%s%s", image, symbol, exactMatch ? "" : " (nearest)"); + else + kprintf("<%s@%p>:unknown", image, (void*)baseAddress); + + kprintf(" + 0x%04lx\n", rip - baseAddress); + } else { + VMArea *area = VMAddressSpace::Kernel()->LookupArea(rip); + if (area != NULL) { + kprintf("%d:%s@%p + %#lx\n", area->id, area->name, + (void*)area->Base(), rip - area->Base()); + } else + kprintf("\n"); + } +} + + void arch_debug_stack_trace(void) { addr_t rbp = x86_read_ebp(); - kprintf("frame caller\n"); + kprintf("frame caller :function" + " + offset\n"); for (int32 callIndex = 0;; callIndex++) { if (rbp == 0) @@ -143,8 +198,7 @@ arch_debug_stack_trace(void) if (is_iframe(rbp)) { struct iframe* frame = (struct iframe*)rbp; print_iframe(frame); - kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, - frame->rbp - rbp, frame->rip); + print_stack_frame(frame->rip, rbp, frame->rbp, callIndex); rbp = frame->rbp; } else { @@ -152,10 +206,9 @@ arch_debug_stack_trace(void) if (frame->return_address == 0) break; - kprintf("%2d %016lx (+%4ld) %016lx\n", callIndex, rbp, - (frame->previous != NULL) - ? (addr_t)frame->previous - rbp : 0, - frame->return_address); + print_stack_frame(frame->return_address, rbp, + (frame->previous != NULL) ? (addr_t)frame->previous : rbp, + callIndex); rbp = (addr_t)frame->previous; } From 5e9bb17da7b9cdd76ff9072486fab90688cf8c36 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 12:14:18 +0100 Subject: [PATCH 086/273] Renamed remaining i386_* functions to x86_* for consistency. --- headers/private/kernel/arch/x86/arch_cpu.h | 2 +- headers/private/kernel/arch/x86/arch_thread.h | 6 +++--- headers/private/kernel/arch/x86/smp_priv.h | 1 - src/system/kernel/arch/x86/32/interrupts.S | 4 ++-- src/system/kernel/arch/x86/arch_cpu.cpp | 2 +- src/system/kernel/arch/x86/arch_debug.cpp | 2 +- src/system/kernel/arch/x86/arch_smp.cpp | 12 +++++------ src/system/kernel/arch/x86/arch_thread.cpp | 13 ++++++------ .../kernel/arch/x86/arch_user_debugger.cpp | 20 +++++++++---------- src/system/kernel/arch/x86/vm86.cpp | 2 +- src/system/kernel/vm/vm.cpp | 2 +- 11 files changed, 32 insertions(+), 34 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 204c901814..17a3d41ece 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -401,7 +401,7 @@ void x86_page_fault_exception_double_fault(struct iframe* frame); #ifndef __x86_64__ -void i386_set_tss_and_kstack(addr_t kstack); +void x86_set_tss_and_kstack(addr_t kstack); void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); void x86_noop_swap(void* oldFpuState, const void* newFpuState); diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 7efd8b11e8..4a08809911 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -17,9 +17,9 @@ extern "C" { #endif -struct iframe* i386_get_user_iframe(void); -struct iframe* i386_get_current_iframe(void); -struct iframe* i386_get_thread_user_iframe(Thread* thread); +struct iframe* x86_get_user_iframe(void); +struct iframe* x86_get_current_iframe(void); +struct iframe* x86_get_thread_user_iframe(Thread* thread); uint32 x86_next_page_directory(Thread* from, Thread* to); diff --git a/headers/private/kernel/arch/x86/smp_priv.h b/headers/private/kernel/arch/x86/smp_priv.h index f5e6f4564e..17b035123c 100644 --- a/headers/private/kernel/arch/x86/smp_priv.h +++ b/headers/private/kernel/arch/x86/smp_priv.h @@ -7,7 +7,6 @@ #include -int i386_smp_interrupt(int vector); void arch_smp_ack_interrupt(void); status_t arch_smp_set_apic_timer(bigtime_t relativeTimeout); status_t arch_smp_clear_apic_timer(void); diff --git a/src/system/kernel/arch/x86/32/interrupts.S b/src/system/kernel/arch/x86/32/interrupts.S index aa4dfe16ac..014fa33c4d 100644 --- a/src/system/kernel/arch/x86/32/interrupts.S +++ b/src/system/kernel/arch/x86/32/interrupts.S @@ -884,7 +884,7 @@ FUNCTION(x86_vm86_enter): pushl THREAD_kernel_stack_top(%edi) movl %esp, THREAD_kernel_stack_top(%edi) pushl %esp - call i386_set_tss_and_kstack + call x86_set_tss_and_kstack // go to vm86 mode cli @@ -916,7 +916,7 @@ FUNCTION(x86_vm86_return): movl %dr3, %edi movl %eax, THREAD_kernel_stack_top(%edi) pushl %eax - call i386_set_tss_and_kstack + call x86_set_tss_and_kstack addl $4, %esp // restore registers diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 2edd3c392d..2c61241a47 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -974,7 +974,7 @@ arch_cpu_init_post_modules(kernel_args* args) #ifndef __x86_64__ void -i386_set_tss_and_kstack(addr_t kstack) +x86_set_tss_and_kstack(addr_t kstack) { get_cpu_struct()->arch.tss.sp0 = kstack; } diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index e8b90927d7..beedfa3b0d 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -503,7 +503,7 @@ static struct iframe* get_current_iframe(Thread* thread) { if (thread == thread_get_current_thread()) - return i386_get_current_iframe(); + return x86_get_current_iframe(); addr_t ebp = thread->arch_info.current_stack.esp[2]; // NOTE: This doesn't work, if the thread is running (on another CPU). diff --git a/src/system/kernel/arch/x86/arch_smp.cpp b/src/system/kernel/arch/x86/arch_smp.cpp index 0720ae0bc6..a63051be29 100644 --- a/src/system/kernel/arch/x86/arch_smp.cpp +++ b/src/system/kernel/arch/x86/arch_smp.cpp @@ -39,7 +39,7 @@ static uint32 sAPICVersions[B_MAX_CPU_COUNT]; static int32 -i386_ici_interrupt(void *data) +x86_ici_interrupt(void *data) { // genuine inter-cpu interrupt int cpu = smp_get_current_cpu(); @@ -49,7 +49,7 @@ i386_ici_interrupt(void *data) static int32 -i386_spurious_interrupt(void *data) +x86_spurious_interrupt(void *data) { // spurious interrupt TRACE(("spurious interrupt on cpu %ld\n", smp_get_current_cpu())); @@ -62,7 +62,7 @@ i386_spurious_interrupt(void *data) static int32 -i386_smp_error_interrupt(void *data) +x86_smp_error_interrupt(void *data) { // smp error interrupt TRACE(("smp error interrupt on cpu %ld\n", smp_get_current_cpu())); @@ -91,9 +91,9 @@ arch_smp_init(kernel_args *args) if (args->num_cpus > 1) { // I/O interrupts start at ARCH_INTERRUPT_BASE, so all interrupts are shifted reserve_io_interrupt_vectors(3, 0xfd - ARCH_INTERRUPT_BASE); - install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE, &i386_ici_interrupt, NULL, B_NO_LOCK_VECTOR); - install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE, &i386_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR); - install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE, &i386_spurious_interrupt, NULL, B_NO_LOCK_VECTOR); + install_io_interrupt_handler(0xfd - ARCH_INTERRUPT_BASE, &x86_ici_interrupt, NULL, B_NO_LOCK_VECTOR); + install_io_interrupt_handler(0xfe - ARCH_INTERRUPT_BASE, &x86_smp_error_interrupt, NULL, B_NO_LOCK_VECTOR); + install_io_interrupt_handler(0xff - ARCH_INTERRUPT_BASE, &x86_spurious_interrupt, NULL, B_NO_LOCK_VECTOR); } return B_OK; diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index ce482bac49..da8e47d739 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -67,7 +67,6 @@ class RestartSyscall : public AbstractTraceEntry { // from arch_interrupts.S -extern "C" void i386_stack_init(struct farcall *interrupt_stack_offset); extern "C" void x86_return_to_userland(iframe* frame); // from arch_cpu.c @@ -160,7 +159,7 @@ initial_return_to_userland(Thread* thread, iframe* frame) // disable interrupts and set up CPU specifics for this thread disable_interrupts(); - i386_set_tss_and_kstack(thread->kernel_stack_top); + x86_set_tss_and_kstack(thread->kernel_stack_top); x86_set_tls_context(thread); x86_set_syscall_stack(thread->kernel_stack_top); @@ -177,7 +176,7 @@ initial_return_to_userland(Thread* thread, iframe* frame) the thread is a kernel thread). */ struct iframe * -i386_get_user_iframe(void) +x86_get_user_iframe(void) { struct iframe* frame = get_current_iframe(); @@ -191,11 +190,11 @@ i386_get_user_iframe(void) } -/*! \brief Like i386_get_user_iframe(), just for the given thread. +/*! \brief Like x86_get_user_iframe(), just for the given thread. The thread must not be running and the threads spinlock must be held. */ struct iframe * -i386_get_thread_user_iframe(Thread *thread) +x86_get_thread_user_iframe(Thread *thread) { if (thread->state == B_THREAD_RUNNING) return NULL; @@ -217,7 +216,7 @@ i386_get_thread_user_iframe(Thread *thread) struct iframe * -i386_get_current_iframe(void) +x86_get_current_iframe(void) { return get_current_iframe(); } @@ -367,7 +366,7 @@ arch_thread_init_tls(Thread *thread) void arch_thread_context_switch(Thread *from, Thread *to) { - i386_set_tss_and_kstack(to->kernel_stack_top); + x86_set_tss_and_kstack(to->kernel_stack_top); x86_set_syscall_stack(to->kernel_stack_top); // set TLS GDT entry to the current thread - since this action is diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp b/src/system/kernel/arch/x86/arch_user_debugger.cpp index 42aaf6f073..99e2b83218 100644 --- a/src/system/kernel/arch/x86/arch_user_debugger.cpp +++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp @@ -516,7 +516,7 @@ debugger_single_step(int argc, char** argv) // TODO: Since we need an iframe, this doesn't work when KDL wasn't entered // via an exception. - struct iframe* frame = i386_get_current_iframe(); + struct iframe* frame = x86_get_current_iframe(); if (frame == NULL) { kprintf("Failed to get the current iframe!\n"); return 0; @@ -568,7 +568,7 @@ arch_destroy_thread_debug_info(struct arch_thread_debug_info *info) void arch_update_thread_single_step() { - if (struct iframe* frame = i386_get_user_iframe()) { + if (struct iframe* frame = x86_get_user_iframe()) { Thread* thread = thread_get_current_thread(); // set/clear TF in EFLAGS depending on whether single stepping is @@ -584,7 +584,7 @@ arch_update_thread_single_step() void arch_set_debug_cpu_state(const debug_cpu_state *cpuState) { - if (struct iframe *frame = i386_get_user_iframe()) { + if (struct iframe *frame = x86_get_user_iframe()) { // For the floating point state to be correct the calling function must // not use these registers (not even indirectly). if (gHasSSE) { @@ -629,7 +629,7 @@ arch_set_debug_cpu_state(const debug_cpu_state *cpuState) void arch_get_debug_cpu_state(debug_cpu_state *cpuState) { - if (struct iframe *frame = i386_get_user_iframe()) { + if (struct iframe *frame = x86_get_user_iframe()) { // For the floating point state to be correct the calling function must // not use these registers (not even indirectly). if (gHasSSE) { @@ -852,7 +852,7 @@ x86_handle_debug_exception(struct iframe *frame) asm("movl %%dr7, %0" : "=r"(dr7)); } - TRACE(("i386_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7)); + TRACE(("x86_handle_debug_exception(): DR6: %lx, DR7: %lx\n", dr6, dr7)); // check, which exception condition applies if (dr6 & X86_DR6_BREAKPOINT_MASK) { @@ -885,7 +885,7 @@ x86_handle_debug_exception(struct iframe *frame) // Occurs only, if GD in DR7 is set (which we don't do) and someone // tries to write to the debug registers. if (IFRAME_IS_USER(frame)) { - dprintf("i386_handle_debug_exception(): ignoring spurious general " + dprintf("x86_handle_debug_exception(): ignoring spurious general " "detect exception\n"); enable_interrupts(); @@ -908,7 +908,7 @@ x86_handle_debug_exception(struct iframe *frame) // kernel entry or whether this is genuine kernel single-stepping. bool inKernel = true; if (thread->team != team_get_kernel_team() - && i386_get_user_iframe() == NULL) { + && x86_get_user_iframe() == NULL) { // TODO: This is not yet fully correct, since a newly created // thread that hasn't entered userland yet also has this // property. @@ -948,7 +948,7 @@ x86_handle_debug_exception(struct iframe *frame) // task switch // Occurs only, if T in EFLAGS is set (which we don't do). if (IFRAME_IS_USER(frame)) { - dprintf("i386_handle_debug_exception(): ignoring spurious task switch " + dprintf("x86_handle_debug_exception(): ignoring spurious task switch " "exception\n"); enable_interrupts(); @@ -956,7 +956,7 @@ x86_handle_debug_exception(struct iframe *frame) panic("spurious task switch exception in kernel mode"); } else { if (IFRAME_IS_USER(frame)) { - TRACE(("i386_handle_debug_exception(): ignoring spurious debug " + TRACE(("x86_handle_debug_exception(): ignoring spurious debug " "exception (no condition recognized)\n")); enable_interrupts(); @@ -974,7 +974,7 @@ x86_handle_debug_exception(struct iframe *frame) void x86_handle_breakpoint_exception(struct iframe *frame) { - TRACE(("i386_handle_breakpoint_exception()\n")); + TRACE(("x86_handle_breakpoint_exception()\n")); // reset eip to the int3 instruction frame->eip--; diff --git a/src/system/kernel/arch/x86/vm86.cpp b/src/system/kernel/arch/x86/vm86.cpp index ebfce515af..948b701019 100644 --- a/src/system/kernel/arch/x86/vm86.cpp +++ b/src/system/kernel/arch/x86/vm86.cpp @@ -512,7 +512,7 @@ emulate(struct vm86_state *state) static bool vm86_fault_callback(addr_t address, addr_t faultAddress, bool isWrite) { - struct iframe *frame = i386_get_user_iframe(); + struct iframe *frame = x86_get_user_iframe(); TRACE("Unhandled fault at %#" B_PRIxADDR " touching %#" B_PRIxADDR "while %s\n", faultAddress, address, isWrite ? "writing" : "reading"); diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 21518a2d4d..b4f00fbbe3 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -4088,7 +4088,7 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, #endif } frame; # ifdef __INTEL__ - struct iframe* iframe = i386_get_user_iframe(); + struct iframe* iframe = x86_get_user_iframe(); if (iframe == NULL) panic("iframe is NULL!"); From 8c5e74719039c7275a5a80b236b830b7b4ba1be7 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 12:25:49 +0100 Subject: [PATCH 087/273] Don't need to shift the factor in system_time(), just store the already shifted value. --- src/system/kernel/arch/x86/arch_cpu.cpp | 3 ++- src/system/libroot/os/arch/x86_64/system_time_asm.S | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 2c61241a47..41713b3a57 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -824,7 +824,8 @@ arch_cpu_init(kernel_args* args) // The x86_64 system_time() implementation uses 64-bit multiplication and // therefore shifting is not necessary for low frequencies (it's also not // too likely that there'll be any x86_64 CPUs clocked under 1GHz). - __x86_setup_system_time(conversionFactor, conversionFactorNsecs); + __x86_setup_system_time((uint64)conversionFactor << 32, + conversionFactorNsecs); #else if (conversionFactorNsecs >> 32 != 0) { // the TSC frequency is < 1 GHz, which forces us to shift the factor diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S index 135b54a4c3..641c86de26 100644 --- a/src/system/libroot/os/arch/x86_64/system_time_asm.S +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -29,9 +29,9 @@ FUNCTION_END(__x86_setup_system_time) /* int64 system_time(); */ FUNCTION(system_time): // (rdtsc * cv_factor) >> 32. + // Factor is pre-shifted left by 32 bits. movq cv_factor, %rcx - shl $32, %rcx // Load 64-bit TSC into %eax (low), %edx (high). rdtsc @@ -43,7 +43,7 @@ FUNCTION(system_time): // Multiply by conversion factor, result in %rax (low), %rdx (high). mulq %rcx - // Conversion factor preshifted by 32, whole result in high. + // Due to pre-shifting of the factor the whole result in high. movq %rdx, %rax ret FUNCTION_END(system_time) @@ -53,7 +53,7 @@ FUNCTION_END(system_time) FUNCTION(system_time_nsecs): // Same algorithm as system_time(), but with a different factor. // (rdtsc * cv_factor_nsecs) >> 32. - // Cannot pre-shift the factor here, otherwise we may lose the upper + // Factor has not been pre-shifted here, otherwise we may lose the upper // 32 bits. movq cv_factor_nsecs, %rcx From 85d4a8bc4e248b992efcde8af001f156cd2c47a9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 14:35:01 +0100 Subject: [PATCH 088/273] Fixed compilation of C code using ELF headers. --- headers/private/system/elf_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h index edfd744b09..31eb0c0ecd 100644 --- a/headers/private/system/elf_common.h +++ b/headers/private/system/elf_common.h @@ -272,7 +272,7 @@ #endif #define DEFINE_ELF_TYPE(type, name) \ struct _ELF_TYPE(type); \ - typedef _ELF_TYPE(type) name + typedef struct _ELF_TYPE(type) name DEFINE_ELF_TYPE(Ehdr, elf_ehdr); DEFINE_ELF_TYPE(Phdr, elf_phdr); From b5c9d24abcc3599375153ed310b495ea944d46a0 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 16:43:01 +0100 Subject: [PATCH 089/273] Implemented threading for x86_64. * Thread creation and switching is working fine, however threads do not yet get interrupted because I've not implemented hardware interrupt handling yet (I'll do that next). * I've made some changes to struct iframe: I've removed the e/r prefixes from the member names for both 32/64, so now they're just named ip, ax, bp, etc. This makes it easier to write code that works with both 32/64 without having to deal with different iframe member names. --- headers/private/kernel/arch/x86/32/iframe.h | 22 +- .../private/kernel/arch/x86/64/descriptors.h | 6 +- headers/private/kernel/arch/x86/64/iframe.h | 18 +- headers/private/kernel/arch/x86/arch_cpu.h | 23 +- headers/private/kernel/arch/x86/arch_debug.h | 2 +- headers/private/kernel/arch/x86/arch_thread.h | 19 +- .../kernel/arch/x86/arch_thread_types.h | 25 +- src/system/kernel/arch/x86/32/arch.S | 6 +- src/system/kernel/arch/x86/32/int.cpp | 66 +-- src/system/kernel/arch/x86/32/interrupts.S | 10 +- src/system/kernel/arch/x86/32/thread.cpp | 396 +++++++++++++++ src/system/kernel/arch/x86/64/arch.S | 56 ++- src/system/kernel/arch/x86/64/int.cpp | 8 +- src/system/kernel/arch/x86/64/interrupts.S | 19 + src/system/kernel/arch/x86/64/stubs.cpp | 120 +---- src/system/kernel/arch/x86/64/thread.cpp | 196 ++++++++ src/system/kernel/arch/x86/Jamfile | 4 +- src/system/kernel/arch/x86/arch_cpu.cpp | 8 +- src/system/kernel/arch/x86/arch_debug.cpp | 76 +-- src/system/kernel/arch/x86/arch_int.cpp | 3 +- src/system/kernel/arch/x86/arch_thread.cpp | 471 ++---------------- .../kernel/arch/x86/arch_user_debugger.cpp | 36 +- src/system/kernel/arch/x86/asm_offsets.cpp | 21 +- src/system/kernel/arch/x86/x86_syscalls.h | 3 + 24 files changed, 923 insertions(+), 691 deletions(-) create mode 100644 src/system/kernel/arch/x86/32/thread.cpp create mode 100644 src/system/kernel/arch/x86/64/thread.cpp diff --git a/headers/private/kernel/arch/x86/32/iframe.h b/headers/private/kernel/arch/x86/32/iframe.h index 6da6c1f9b2..1aa51ed90a 100644 --- a/headers/private/kernel/arch/x86/32/iframe.h +++ b/headers/private/kernel/arch/x86/32/iframe.h @@ -15,25 +15,25 @@ struct iframe { uint32 fs; uint32 es; uint32 ds; - uint32 edi; - uint32 esi; - uint32 ebp; - uint32 esp; - uint32 ebx; - uint32 edx; - uint32 ecx; - uint32 eax; + uint32 di; + uint32 si; + uint32 bp; + uint32 sp; + uint32 bx; + uint32 dx; + uint32 cx; + uint32 ax; uint32 orig_eax; uint32 orig_edx; uint32 vector; uint32 error_code; - uint32 eip; + uint32 ip; uint32 cs; uint32 flags; - // user_esp and user_ss are only present when the iframe is a userland + // user_sp and user_ss are only present when the iframe is a userland // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. - uint32 user_esp; + uint32 user_sp; uint32 user_ss; }; diff --git a/headers/private/kernel/arch/x86/64/descriptors.h b/headers/private/kernel/arch/x86/64/descriptors.h index 8e70cba67e..3f05196586 100644 --- a/headers/private/kernel/arch/x86/64/descriptors.h +++ b/headers/private/kernel/arch/x86/64/descriptors.h @@ -76,9 +76,9 @@ struct gdt_idt_descr { struct tss { uint32 _reserved1; - uint64 rsp0; - uint64 rsp1; - uint64 rsp2; + uint64 sp0; + uint64 sp1; + uint64 sp2; uint64 _reserved2; uint64 ist1; uint64 ist2; diff --git a/headers/private/kernel/arch/x86/64/iframe.h b/headers/private/kernel/arch/x86/64/iframe.h index a0ca48f2c4..cd257ef6ea 100644 --- a/headers/private/kernel/arch/x86/64/iframe.h +++ b/headers/private/kernel/arch/x86/64/iframe.h @@ -16,21 +16,21 @@ struct iframe { uint64 r10; uint64 r9; uint64 r8; - uint64 rbp; - uint64 rsi; - uint64 rdi; - uint64 rdx; - uint64 rcx; - uint64 rbx; - uint64 rax; + uint64 bp; + uint64 si; + uint64 di; + uint64 dx; + uint64 cx; + uint64 bx; + uint64 ax; uint64 vector; uint64 error_code; - uint64 rip; + uint64 ip; uint64 cs; uint64 flags; // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). - uint64 user_rsp; + uint64 user_sp; uint64 user_ss; } _PACKED; diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 17a3d41ece..32f0129c31 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -24,10 +24,6 @@ #endif // !_ASSEMBLER -#undef PAUSE -#define PAUSE() asm volatile ("pause;") - - // MSR registers (possibly Intel specific) #define IA32_MSR_TSC 0x10 #define IA32_MSR_APIC_BASE 0x1b @@ -40,6 +36,14 @@ #define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 #define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 +// x86_64 MSRs. +#define IA32_MSR_STAR 0xc0000081 +#define IA32_MSR_LSTAR 0xc0000082 +#define IA32_MSR_FMASK 0xc0000084 +#define IA32_MSR_FS_BASE 0xc0000100 +#define IA32_MSR_GS_BASE 0xc0000101 +#define IA32_MSR_KERNEL_GS_BASE 0xc0000102 + // K8 MSR registers #define K8_MSR_IPM 0xc0010055 @@ -268,6 +272,9 @@ typedef struct arch_cpu_info { } arch_cpu_info; +#undef PAUSE +#define PAUSE() asm volatile ("pause;") + #define nop() __asm__ ("nop"::) #define x86_read_cr0() ({ \ @@ -379,11 +386,13 @@ void x86_context_switch(struct arch_thread* oldState, struct arch_thread* newState); void x86_userspace_thread_exit(void); void x86_end_userspace_thread_exit(void); -void x86_swap_pgdir(uint32 newPageDir); +void x86_swap_pgdir(addr_t newPageDir); +void x86_set_tss_and_kstack(addr_t kstack); void x86_fxsave(void* fpuState); void x86_fxrstor(const void* fpuState); +void x86_noop_swap(void* oldFpuState, const void* newFpuState); void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); -addr_t x86_read_ebp(); +addr_t x86_get_stack_frame(); uint64 x86_read_msr(uint32 registerNumber); void x86_write_msr(uint32 registerNumber, uint64 value); void* x86_get_idt(int32 cpu); @@ -401,10 +410,8 @@ void x86_page_fault_exception_double_fault(struct iframe* frame); #ifndef __x86_64__ -void x86_set_tss_and_kstack(addr_t kstack); void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); -void x86_noop_swap(void* oldFpuState, const void* newFpuState); void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); void x86_set_task_gate(int32 cpu, int32 n, int32 segment); int32 x86_double_fault_get_cpu(void); diff --git a/headers/private/kernel/arch/x86/arch_debug.h b/headers/private/kernel/arch/x86/arch_debug.h index 789ecc7461..eb2028ffe5 100644 --- a/headers/private/kernel/arch/x86/arch_debug.h +++ b/headers/private/kernel/arch/x86/arch_debug.h @@ -10,7 +10,7 @@ struct arch_debug_registers { - uint32 ebp; + addr_t bp; }; diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 4a08809911..850cfc9973 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -16,35 +16,40 @@ extern "C" { #endif +struct sigaction; + struct iframe* x86_get_user_iframe(void); struct iframe* x86_get_current_iframe(void); struct iframe* x86_get_thread_user_iframe(Thread* thread); -uint32 x86_next_page_directory(Thread* from, Thread* to); +phys_addr_t x86_next_page_directory(Thread* from, Thread* to); +void x86_initial_return_to_userland(Thread* thread, struct iframe* iframe); +uint8* x86_get_signal_stack(Thread* thread, struct iframe* frame, + struct sigaction* action); void x86_restart_syscall(struct iframe* frame); - void x86_set_tls_context(Thread* thread); #ifdef __x86_64__ -// TODO - -extern Thread* gCurrentThread; static inline Thread* arch_thread_get_current_thread(void) { - return gCurrentThread; + addr_t addr; + __asm__("mov %%gs:0, %0" : "=r"(addr)); + return (Thread*)addr; } static inline void arch_thread_set_current_thread(Thread* t) { - gCurrentThread = t; + // Point GS segment base at thread architecture data. + t->arch_info.thread = t; + x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&t->arch_info); } diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 900046fd0b..209543e7ba 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -12,27 +12,42 @@ #include +namespace BKernel { + struct Thread; +} + + #define _ALIGNED(bytes) __attribute__((aligned(bytes))) // move this to somewhere else, maybe BeBuild.h? +#ifndef __x86_64__ struct farcall { uint32* esp; uint32* ss; }; +#endif // architecture specific thread info struct arch_thread { #ifdef __x86_64__ - uint64* rsp; + // Back pointer to the containing Thread structure. The GS segment base is + // pointed here, used to get the current thread. + BKernel::Thread* thread; + + // RSP for kernel entry used by SYSCALL, and temporary scratch space. + uint64* syscall_rsp; + uint64* user_rsp; + + uint64* current_stack; #else - struct farcall current_stack; - struct farcall interrupt_stack; + struct farcall current_stack; + struct farcall interrupt_stack; #endif // 512 byte floating point save point - this must be 16 byte aligned - uint8 fpu_state[512] _ALIGNED(16); + uint8 fpu_state[512] _ALIGNED(16); } _ALIGNED(16); @@ -40,7 +55,7 @@ struct arch_team { // gcc treats empty structures as zero-length in C, but as if they contain // a char in C++. So we have to put a dummy in to be able to use the struct // from both in a consistent way. - char dummy; + char dummy; }; diff --git a/src/system/kernel/arch/x86/32/arch.S b/src/system/kernel/arch/x86/32/arch.S index e966580dbe..97eb069a40 100644 --- a/src/system/kernel/arch/x86/32/arch.S +++ b/src/system/kernel/arch/x86/32/arch.S @@ -71,11 +71,11 @@ FUNCTION(x86_fxsave_swap): ret FUNCTION_END(x86_fxsave_swap) -/* uint32 x86_read_ebp(); */ -FUNCTION(x86_read_ebp): +/* uint32 x86_get_stack_frame(); */ +FUNCTION(x86_get_stack_frame): movl %ebp, %eax ret -FUNCTION_END(x86_read_ebp) +FUNCTION_END(x86_get_stack_frame) /* uint64 x86_read_msr(uint32 register); */ FUNCTION(x86_read_msr): diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index d35e3f0c63..acfc11778b 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -161,7 +161,7 @@ invalid_exception(struct iframe* frame) char name[32]; panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->eip, thread ? thread->id : -1); + frame->ip, thread ? thread->id : -1); } @@ -194,14 +194,14 @@ unexpected_exception(struct iframe* frame) type = B_DIVIDE_ERROR; signalNumber = SIGFPE; signalCode = FPE_INTDIV; - signalAddress = frame->eip; + signalAddress = frame->ip; break; case 4: // Overflow Exception (#OF) type = B_OVERFLOW_EXCEPTION; signalNumber = SIGFPE; signalCode = FPE_INTOVF; - signalAddress = frame->eip; + signalAddress = frame->ip; break; case 5: // BOUND Range Exceeded Exception (#BR) @@ -214,14 +214,14 @@ unexpected_exception(struct iframe* frame) type = B_INVALID_OPCODE_EXCEPTION; signalNumber = SIGILL; signalCode = ILL_ILLOPC; - signalAddress = frame->eip; + signalAddress = frame->ip; break; case 13: // General Protection Exception (#GP) type = B_GENERAL_PROTECTION_FAULT; signalNumber = SIGILL; signalCode = ILL_PRVOPC; // or ILL_PRVREG - signalAddress = frame->eip; + signalAddress = frame->ip; break; case 16: // x87 FPU Floating-Point Error (#MF) @@ -230,7 +230,7 @@ unexpected_exception(struct iframe* frame) signalCode = FPE_FLTDIV; // TODO: Determine the correct cause via the FPU status // register! - signalAddress = frame->eip; + signalAddress = frame->ip; break; case 17: // Alignment Check Exception (#AC) @@ -247,7 +247,7 @@ unexpected_exception(struct iframe* frame) signalNumber = SIGFPE; signalCode = FPE_FLTDIV; // TODO: Determine the correct cause via the MXCSR register! - signalAddress = frame->eip; + signalAddress = frame->ip; break; default: @@ -300,15 +300,15 @@ x86_double_fault_exception(struct iframe* frame) frame->ds = tss->ds; frame->fs = tss->fs; frame->gs = tss->gs; - frame->eip = tss->eip; - frame->ebp = tss->ebp; - frame->esp = tss->esp; - frame->eax = tss->eax; - frame->ebx = tss->ebx; - frame->ecx = tss->ecx; - frame->edx = tss->edx; - frame->esi = tss->esi; - frame->edi = tss->edi; + frame->ip = tss->eip; + frame->bp = tss->ebp; + frame->sp = tss->esp; + frame->ax = tss->eax; + frame->bx = tss->ebx; + frame->cx = tss->ecx; + frame->dx = tss->edx; + frame->si = tss->esi; + frame->di = tss->edi; frame->flags = tss->eflags; // Use a special handler for page faults which avoids the triple fault @@ -328,10 +328,10 @@ x86_page_fault_exception_double_fault(struct iframe* frame) cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; addr_t faultHandler = cpu.fault_handler; if (faultHandler != 0) { - debug_set_page_fault_info(cr2, frame->eip, + debug_set_page_fault_info(cr2, frame->ip, (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = faultHandler; - frame->ebp = cpu.fault_handler_stack_pointer; + frame->ip = faultHandler; + frame->bp = cpu.fault_handler_stack_pointer; return; } @@ -340,7 +340,7 @@ x86_page_fault_exception_double_fault(struct iframe* frame) // print the info we've got and enter an infinite loop. kprintf("Page fault in double fault debugger without fault handler! " "Touching address %p from eip %p. Entering infinite loop...\n", - (void*)cr2, (void*)frame->eip); + (void*)cr2, (void*)frame->ip); while (true); } @@ -359,28 +359,28 @@ page_fault_exception(struct iframe* frame) if (thread != NULL) { cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; if (cpu->fault_handler != 0) { - debug_set_page_fault_info(cr2, frame->eip, + debug_set_page_fault_info(cr2, frame->ip, (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = cpu->fault_handler; - frame->ebp = cpu->fault_handler_stack_pointer; + frame->ip = cpu->fault_handler; + frame->bp = cpu->fault_handler_stack_pointer; return; } if (thread->fault_handler != 0) { kprintf("ERROR: thread::fault_handler used in kernel " "debugger!\n"); - debug_set_page_fault_info(cr2, frame->eip, + debug_set_page_fault_info(cr2, frame->ip, (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->eip = thread->fault_handler; + frame->ip = thread->fault_handler; return; } } // otherwise, not really panic("page fault in debugger without fault handler! Touching " - "address %p from eip %p\n", (void *)cr2, (void *)frame->eip); + "address %p from eip %p\n", (void *)cr2, (void *)frame->ip); return; } else if ((frame->flags & 0x200) == 0) { // interrupts disabled @@ -390,8 +390,8 @@ page_fault_exception(struct iframe* frame) // disabled, which in most cases is a bug. We should add some thread // flag allowing to explicitly indicate that this handling is desired. if (thread && thread->fault_handler != 0) { - if (frame->eip != thread->fault_handler) { - frame->eip = thread->fault_handler; + if (frame->ip != thread->fault_handler) { + frame->ip = thread->fault_handler; return; } @@ -399,30 +399,30 @@ page_fault_exception(struct iframe* frame) // certain infinite loop. panic("page fault, interrupts disabled, fault handler loop. " "Touching address %p from eip %p\n", (void*)cr2, - (void*)frame->eip); + (void*)frame->ip); } // If we are not running the kernel startup the page fault was not // allowed to happen and we must panic. panic("page fault, but interrupts were disabled. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->eip); + "%p from eip %p\n", (void *)cr2, (void *)frame->ip); return; } else if (thread != NULL && thread->page_faults_allowed < 1) { panic("page fault not allowed at this place. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->eip); + "%p from eip %p\n", (void *)cr2, (void *)frame->ip); return; } enable_interrupts(); - vm_page_fault(cr2, frame->eip, + vm_page_fault(cr2, frame->ip, (frame->error_code & 0x2) != 0, // write access (frame->error_code & 0x4) != 0, // userland &newip); if (newip != 0) { // the page fault handler wants us to modify the iframe to set the // IP the cpu will return to to be this ip - frame->eip = newip; + frame->ip = newip; } } diff --git a/src/system/kernel/arch/x86/32/interrupts.S b/src/system/kernel/arch/x86/32/interrupts.S index 014fa33c4d..ea3cd5e5a4 100644 --- a/src/system/kernel/arch/x86/32/interrupts.S +++ b/src/system/kernel/arch/x86/32/interrupts.S @@ -138,7 +138,7 @@ subl $80, %esp; \ \ /* get the address of the syscall parameters */ \ - movl IFRAME_user_esp(%ebp), %esi; \ + movl IFRAME_user_sp(%ebp), %esi; \ addl $4, %esi; \ cmp $KERNEL_BASE, %esi; /* must not be a kernel address */ \ jae bad_syscall_params; \ @@ -673,8 +673,8 @@ STATIC_FUNCTION(handle_syscall): // overwrite the values of %eax and %edx on the stack (the syscall return // value) - movl %edx, IFRAME_edx(%ebp) - movl %eax, IFRAME_eax(%ebp) + movl %edx, IFRAME_dx(%ebp) + movl %eax, IFRAME_ax(%ebp) TRACE_POST_SYSCALL() @@ -725,8 +725,8 @@ FUNCTION_END(handle_syscall) jz 1f pushl -8(%ebp) // syscall start time pushl -12(%ebp) - movl IFRAME_edx(%ebp), %edx // syscall return value - movl IFRAME_eax(%ebp), %eax + movl IFRAME_dx(%ebp), %edx // syscall return value + movl IFRAME_ax(%ebp), %eax push %edx push %eax lea 16(%esp), %eax // syscall parameters diff --git a/src/system/kernel/arch/x86/32/thread.cpp b/src/system/kernel/arch/x86/32/thread.cpp new file mode 100644 index 0000000000..4df16852d7 --- /dev/null +++ b/src/system/kernel/arch/x86/32/thread.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "paging/X86PagingStructures.h" +#include "paging/X86VMTranslationMap.h" +#include "x86_signals.h" + + +//#define TRACE_ARCH_THREAD +#ifdef TRACE_ARCH_THREAD +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + + +#ifdef SYSCALL_TRACING + +namespace SyscallTracing { + +class RestartSyscall : public AbstractTraceEntry { + public: + RestartSyscall() + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("syscall restart"); + } +}; + +} + +# define TSYSCALL(x) new(std::nothrow) SyscallTracing::x + +#else +# define TSYSCALL(x) +#endif // SYSCALL_TRACING + + +// from arch_cpu.cpp +extern bool gHasSSE; + +static struct arch_thread sInitialState _ALIGNED(16); + // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it + + +static inline void +set_fs_register(uint32 segment) +{ + asm("movl %0,%%fs" :: "r" (segment)); +} + + +void +x86_restart_syscall(struct iframe* frame) +{ + Thread* thread = thread_get_current_thread(); + + atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); + atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); + + frame->ax = frame->orig_eax; + frame->dx = frame->orig_edx; + frame->ip -= 2; + // undoes the "int $99"/"sysenter"/"syscall" instruction + // (so that it'll be executed again) + + TSYSCALL(RestartSyscall()); +} + + +void +x86_set_tls_context(Thread *thread) +{ + int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT; + + set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage); + set_fs_register((entry << 3) | DPL_USER); +} + + +// #pragma mark - + + +status_t +arch_thread_init(struct kernel_args *args) +{ + // save one global valid FPU state; it will be copied in the arch dependent + // part of each new thread + + asm volatile ("clts; fninit; fnclex;"); + if (gHasSSE) + x86_fxsave(sInitialState.fpu_state); + else + x86_fnsave(sInitialState.fpu_state); + + return B_OK; +} + + +status_t +arch_thread_init_thread_struct(Thread *thread) +{ + // set up an initial state (stack & fpu) + memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread)); + return B_OK; +} + + +/*! Prepares the given thread's kernel stack for executing its entry function. + + \param thread The thread. + \param stack The usable bottom of the thread's kernel stack. + \param stackTop The usable top of the thread's kernel stack. + \param function The entry function the thread shall execute. + \param data Pointer to be passed to the entry function. +*/ +void +arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, + void (*function)(void*), const void* data) +{ + addr_t* stackTop = (addr_t*)_stackTop; + + TRACE(("arch_thread_init_kthread_stack: stack top %p, function %p, data: " + "%p\n", stackTop, function, data)); + + // push the function argument, a pointer to the data + *--stackTop = (addr_t)data; + + // push a dummy return address for the function + *--stackTop = 0; + + // push the function address -- that's the return address used after the + // context switch + *--stackTop = (addr_t)function; + + // simulate pushad as done by x86_context_switch() + for (int i = 0; i < 8; i++) + *--stackTop = 0; + + // save the stack position + thread->arch_info.current_stack.esp = stackTop; + thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG; +} + + +/*! Initializes the user-space TLS local storage pointer in + the thread structure, and the reserved TLS slots. + + Is called from _create_user_thread_kentry(). +*/ +status_t +arch_thread_init_tls(Thread *thread) +{ + uint32 tls[TLS_USER_THREAD_SLOT + 1]; + + thread->user_local_storage = thread->user_stack_base + + thread->user_stack_size; + + // initialize default TLS fields + memset(tls, 0, sizeof(tls)); + tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; + tls[TLS_THREAD_ID_SLOT] = thread->id; + tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; + + return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls)); +} + + +void +arch_thread_dump_info(void *info) +{ + struct arch_thread *at = (struct arch_thread *)info; + + kprintf("\tesp: %p\n", at->current_stack.esp); + kprintf("\tss: %p\n", at->current_stack.ss); + kprintf("\tfpu_state at %p\n", at->fpu_state); +} + + +/*! Sets up initial thread context and enters user space +*/ +status_t +arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, + void* args2) +{ + addr_t stackTop = thread->user_stack_base + thread->user_stack_size; + uint32 codeSize = (addr_t)x86_end_userspace_thread_exit + - (addr_t)x86_userspace_thread_exit; + uint32 args[3]; + + TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, " + "ustack_top 0x%lx\n", entry, args1, args2, stackTop)); + + // copy the little stub that calls exit_thread() when the thread entry + // function returns, as well as the arguments of the entry function + stackTop -= codeSize; + + if (user_memcpy((void *)stackTop, (const void *)&x86_userspace_thread_exit, codeSize) < B_OK) + return B_BAD_ADDRESS; + + args[0] = stackTop; + args[1] = (uint32)args1; + args[2] = (uint32)args2; + stackTop -= sizeof(args); + + if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) + return B_BAD_ADDRESS; + + // prepare the user iframe + iframe frame = {}; + frame.type = IFRAME_TYPE_SYSCALL; + frame.gs = USER_DATA_SEG; + // frame.fs not used, we call x86_set_tls_context() on context switch + frame.es = USER_DATA_SEG; + frame.ds = USER_DATA_SEG; + frame.ip = entry; + frame.cs = USER_CODE_SEG; + frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT + | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); + frame.user_sp = stackTop; + frame.user_ss = USER_DATA_SEG; + + // return to userland + x86_initial_return_to_userland(thread, &frame); + + return B_OK; + // never gets here +} + + +/*! Sets up the user iframe for invoking a signal handler. + + The function fills in the remaining fields of the given \a signalFrameData, + copies it to the thread's userland stack (the one on which the signal shall + be handled), and sets up the user iframe so that when returning to userland + a wrapper function is executed that calls the user-defined signal handler. + When the signal handler returns, the wrapper function shall call the + "restore signal frame" syscall with the (possibly modified) signal frame + data. + + The following fields of the \a signalFrameData structure still need to be + filled in: + - \c context.uc_stack: The stack currently used by the thread. + - \c context.uc_mcontext: The current userland state of the registers. + - \c syscall_restart_return_value: Architecture specific use. On x86 the + value of eax and edx which are overwritten by the syscall return value. + + Furthermore the function needs to set \c thread->user_signal_context to the + userland pointer to the \c ucontext_t on the user stack. + + \param thread The current thread. + \param action The signal action specified for the signal to be handled. + \param signalFrameData A partially initialized structure of all the data + that need to be copied to userland. + \return \c B_OK on success, another error code, if something goes wrong. +*/ +status_t +arch_setup_signal_frame(Thread* thread, struct sigaction* action, + struct signal_frame_data* signalFrameData) +{ + struct iframe *frame = x86_get_current_iframe(); + if (!IFRAME_IS_USER(frame)) { + panic("arch_setup_signal_frame(): No user iframe!"); + return B_BAD_VALUE; + } + + // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since they + // had the same signal number. + if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0 + && signalFrameData->info.si_signo == SIGBUS) { + signalFrameData->info.si_signo = SIGSEGV; + } + + // store the register state in signalFrameData->context.uc_mcontext + signalFrameData->context.uc_mcontext.eip = frame->ip; + signalFrameData->context.uc_mcontext.eflags = frame->flags; + signalFrameData->context.uc_mcontext.eax = frame->ax; + signalFrameData->context.uc_mcontext.ecx = frame->cx; + signalFrameData->context.uc_mcontext.edx = frame->dx; + signalFrameData->context.uc_mcontext.ebp = frame->bp; + signalFrameData->context.uc_mcontext.esp = frame->user_sp; + signalFrameData->context.uc_mcontext.edi = frame->di; + signalFrameData->context.uc_mcontext.esi = frame->si; + signalFrameData->context.uc_mcontext.ebx = frame->bx; + x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); + + // fill in signalFrameData->context.uc_stack + signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); + + // store orig_eax/orig_edx in syscall_restart_return_value + signalFrameData->syscall_restart_return_value + = (uint64)frame->orig_edx << 32 | frame->orig_eax; + + // get the stack to use -- that's either the current one or a special signal + // stack + uint8* userStack = x86_get_signal_stack(thread, frame, action); + + // copy the signal frame data onto the stack + userStack -= sizeof(*signalFrameData); + signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; + if (user_memcpy(userSignalFrameData, signalFrameData, + sizeof(*signalFrameData)) != B_OK) { + return B_BAD_ADDRESS; + } + + // prepare the user stack frame for a function call to the signal handler + // wrapper function + uint32 stackFrame[2] = { + frame->ip, // return address + (addr_t)userSignalFrameData, // parameter: pointer to signal frame data + }; + + userStack -= sizeof(stackFrame); + if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) + return B_BAD_ADDRESS; + + // Update Thread::user_signal_context, now that everything seems to have + // gone fine. + thread->user_signal_context = &userSignalFrameData->context; + + // Adjust the iframe's esp and eip, so that the thread will continue with + // the prepared stack, executing the signal handler wrapper function. + frame->user_sp = (addr_t)userStack; + frame->ip = x86_get_user_signal_handler_wrapper( + (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0); + + return B_OK; +} + + +int64 +arch_restore_signal_frame(struct signal_frame_data* signalFrameData) +{ + struct iframe* frame = x86_get_current_iframe(); + + TRACE(("### arch_restore_signal_frame: entry\n")); + + frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value; + frame->orig_edx + = (uint32)(signalFrameData->syscall_restart_return_value >> 32); + + frame->ip = signalFrameData->context.uc_mcontext.eip; + frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS) + | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); + frame->ax = signalFrameData->context.uc_mcontext.eax; + frame->cx = signalFrameData->context.uc_mcontext.ecx; + frame->dx = signalFrameData->context.uc_mcontext.edx; + frame->bp = signalFrameData->context.uc_mcontext.ebp; + frame->user_sp = signalFrameData->context.uc_mcontext.esp; + frame->di = signalFrameData->context.uc_mcontext.edi; + frame->si = signalFrameData->context.uc_mcontext.esi; + frame->bx = signalFrameData->context.uc_mcontext.ebx; + + x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); + + TRACE(("### arch_restore_signal_frame: exit\n")); + + return (int64)frame->ax | ((int64)frame->dx << 32); +} + + +void +arch_syscall_64_bit_return_value(void) +{ + Thread* thread = thread_get_current_thread(); + atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); +} diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index eb51f75691..4fe65734c1 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -6,6 +6,8 @@ #include +#include "asm_offsets.h" + .text @@ -24,6 +26,13 @@ FUNCTION(x86_fxrstor): FUNCTION_END(x86_fxrstor) +/* void x86_noop_swap(void *oldFpuState, const void *newFpuState); */ +FUNCTION(x86_noop_swap): + nop + ret +FUNCTION_END(x86_noop_swap) + + /* void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); */ FUNCTION(x86_fxsave_swap): fxsave (%rdi) @@ -32,11 +41,11 @@ FUNCTION(x86_fxsave_swap): FUNCTION_END(x86_fxsave_swap) -/* addr_t x86_read_ebp(); */ -FUNCTION(x86_read_ebp): +/* addr_t x86_get_stack_frame(); */ +FUNCTION(x86_get_stack_frame): mov %rbp, %rax ret -FUNCTION_END(x86_read_ebp) +FUNCTION_END(x86_get_stack_frame) /* uint64 x86_read_msr(uint32 register); */ @@ -61,6 +70,47 @@ FUNCTION(x86_write_msr): FUNCTION_END(x86_write_msr) +/* void x86_64_thread_entry(); */ +FUNCTION(x86_64_thread_entry): + movq %r15, %rdi + jmp *%r14 +FUNCTION_END(x86_64_thread_entry) + + +/* void x86_context_switch(struct arch_thread* oldState, + struct arch_thread* newState); */ +FUNCTION(x86_context_switch): + // Just need to save callee-save registers: RBP, RBX, R12-15. + push %r15 + push %r14 + push %r13 + push %r12 + push %rbp + push %rbx + + // Swap the stack pointers. + movq %rsp, ARCH_THREAD_current_stack(%rdi) + movq ARCH_THREAD_current_stack(%rsi), %rsp + + // Restore callee-save registers. + pop %rbx + pop %rbp + pop %r12 + pop %r13 + pop %r14 + pop %r15 + + ret +FUNCTION_END(x86_context_switch) + + +/* void x86_swap_pgdir(uint64 newPageDir); */ +FUNCTION(x86_swap_pgdir): + movq %rdi, %cr3 + ret +FUNCTION_END(x86_swap_pgdir) + + null_idt_descr: .word 0 .quad 0 diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index bbc5850ebb..6117171e30 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -72,7 +72,7 @@ invalid_exception(iframe* frame) char name[32]; panic("unhandled trap %#lx (%s) at ip %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->rip); + frame->ip); } @@ -82,7 +82,7 @@ fatal_exception(iframe* frame) char name[32]; panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->rip, frame->error_code); + frame->ip, frame->error_code); } @@ -92,7 +92,7 @@ unexpected_exception(iframe* frame) char name[32]; panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->rip, frame->error_code); + frame->ip, frame->error_code); } @@ -102,7 +102,7 @@ page_fault_exception(iframe* frame) addr_t cr2 = x86_read_cr2(); panic("page fault exception at ip %#lx on %#lx, error code %#lx\n", - frame->rip, cr2, frame->error_code); + frame->ip, cr2, frame->error_code); } diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index d5f8fcad30..7987ed27a8 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -111,6 +111,7 @@ SYMBOL(isr_array): .Lintr = .Lintr+1 .endr + // Common interrupt handling code. FUNCTION(int_bottom): // If coming from user-mode, need to load the kernel GS segment base. @@ -141,3 +142,21 @@ FUNCTION(int_bottom): jz 2f swapgs 2: iretq +FUNCTION_END(int_bottom) + + +/*! \fn void x86_return_to_userland(iframe* frame) + \brief Returns to the userland environment given by \a frame. + + Before returning to userland all potentially necessary kernel exit work is + done. + + \a frame must point to a location somewhere on the caller's stack (e.g. a + local variable). + The function must be called with interrupts disabled. + + \param frame The iframe defining the userland environment. +*/ +FUNCTION(x86_return_to_userland): + ud2a +FUNCTION_END(x86_return_to_userland) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 5f85b9aa2a..2651c32a47 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -37,10 +37,6 @@ #include -// temporary -Thread* gCurrentThread = NULL; - - status_t arch_commpage_init(void) { @@ -106,23 +102,23 @@ print_iframe(struct iframe* frame) bool isUser = IFRAME_IS_USER(frame); kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, - isUser ? (uint64*)(frame + 1) : &frame->user_rsp); + isUser ? (uint64*)(frame + 1) : &frame->user_sp); - kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%lx\n", frame->rax, - frame->rbx, frame->rcx); - kprintf(" rdx 0x%-16lx rsi 0x%-16lx rdi 0x%lx\n", frame->rdx, - frame->rsi, frame->rdi); - kprintf(" rbp 0x%-16lx r8 0x%-16lx r9 0x%lx\n", frame->rbp, + kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%lx\n", frame->ax, + frame->bx, frame->cx); + kprintf(" rdx 0x%-16lx rsi 0x%-16lx rdi 0x%lx\n", frame->dx, + frame->si, frame->di); + kprintf(" rbp 0x%-16lx r8 0x%-16lx r9 0x%lx\n", frame->bp, frame->r8, frame->r9); kprintf(" r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", frame->r10, frame->r11, frame->r12); kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%lx\n", frame->r13, frame->r14, frame->r15); - kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->rip, frame->flags); + kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->ip, frame->flags); if (isUser) { // from user space - kprintf("user rsp 0x%lx", frame->user_rsp); + kprintf("user rsp 0x%lx", frame->user_sp); } kprintf("\n"); kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, @@ -186,7 +182,7 @@ print_stack_frame(addr_t rip, addr_t rbp, addr_t nextRbp, int32 callIndex) void arch_debug_stack_trace(void) { - addr_t rbp = x86_read_ebp(); + addr_t rbp = x86_get_stack_frame(); kprintf("frame caller :function" " + offset\n"); @@ -198,9 +194,9 @@ arch_debug_stack_trace(void) if (is_iframe(rbp)) { struct iframe* frame = (struct iframe*)rbp; print_iframe(frame); - print_stack_frame(frame->rip, rbp, frame->rbp, callIndex); + print_stack_frame(frame->ip, rbp, frame->bp, callIndex); - rbp = frame->rbp; + rbp = frame->bp; } else { stack_frame* frame = (stack_frame*)rbp; if (frame->return_address == 0) @@ -374,100 +370,6 @@ arch_system_info_init(struct kernel_args *args) } -status_t -arch_thread_init(struct kernel_args *args) -{ - return B_ERROR; -} - - -status_t -arch_team_init_team_struct(Team *p, bool kernel) -{ - return B_OK; -} - - -status_t -arch_thread_init_thread_struct(Thread *thread) -{ - return B_ERROR; -} - - -void -arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, - void (*function)(void*), const void* data) -{ - -} - - -status_t -arch_thread_init_tls(Thread *thread) -{ - return B_ERROR; -} - - -void -arch_thread_context_switch(Thread *from, Thread *to) -{ - -} - - -void -arch_thread_dump_info(void *info) -{ - -} - - -status_t -arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, - void* args2) -{ - return B_ERROR; -} - - -bool -arch_on_signal_stack(Thread *thread) -{ - return false; -} - - -status_t -arch_setup_signal_frame(Thread* thread, struct sigaction* action, - struct signal_frame_data* signalFrameData) -{ - return B_ERROR; -} - - -int64 -arch_restore_signal_frame(struct signal_frame_data* signalFrameData) -{ - return 0; -} - - -void -arch_store_fork_frame(struct arch_fork_arg *arg) -{ - -} - - -void -arch_restore_fork_frame(struct arch_fork_arg* arg) -{ - -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp new file mode 100644 index 0000000000..b4e9d8ac41 --- /dev/null +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -0,0 +1,196 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "paging/X86PagingStructures.h" +#include "paging/X86VMTranslationMap.h" + + +//#define TRACE_ARCH_THREAD +#ifdef TRACE_ARCH_THREAD +# define TRACE(x...) dprintf(x) +#else +# define TRACE(x...) ; +#endif + + +extern "C" void x86_64_thread_entry(); + +// Initial thread saved state. +static arch_thread sInitialState; + + +void +x86_set_tls_context(Thread* thread) +{ + +} + + +// #pragma mark - + + +status_t +arch_thread_init(kernel_args* args) +{ + // Save one global valid FPU state; it will be copied in the arch dependent + // part of each new thread. + asm volatile ("clts; fninit; fnclex;"); + x86_fxsave(sInitialState.fpu_state); + + return B_OK; +} + + +status_t +arch_thread_init_thread_struct(Thread* thread) +{ + // Copy the initial saved FPU state to the new thread. + memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread)); + + // Initialise the current thread pointer. + thread->arch_info.thread = thread; + + return B_OK; +} + + +/*! Prepares the given thread's kernel stack for executing its entry function. + + \param thread The thread. + \param stack The usable bottom of the thread's kernel stack. + \param stackTop The usable top of the thread's kernel stack. + \param function The entry function the thread shall execute. + \param data Pointer to be passed to the entry function. +*/ +void +arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, + void (*function)(void*), const void* data) +{ + addr_t* stackTop = (addr_t*)_stackTop; + + TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " + "%p\n", _stackTop, function, data); + + // x86_64 uses registers for argument passing, first argument in RDI, + // however we don't save RDI on every context switch (there is no need + // for us to: it is not callee-save, and only contains the first argument + // to x86_context_switch). However, this presents a problem since we + // cannot store the argument for the entry function here. Therefore, we + // save the function address in R14 and the argument in R15 (which are + // restored), and then set up the stack to initially call a wrapper + // function which passes the argument correctly. + + *--stackTop = 0; // Dummy return address. + *--stackTop = (addr_t)x86_64_thread_entry; // Wrapper function. + *--stackTop = (addr_t)data; // R15: argument. + *--stackTop = (addr_t)function; // R14: entry function. + *--stackTop = 0; // R13. + *--stackTop = 0; // R12. + *--stackTop = 0; // RBP. + *--stackTop = 0; // RBX. + + // Save the stack position. + thread->arch_info.current_stack = stackTop; +} + + +/*! Initializes the user-space TLS local storage pointer in + the thread structure, and the reserved TLS slots. + + Is called from _create_user_thread_kentry(). +*/ +status_t +arch_thread_init_tls(Thread* thread) +{ + dprintf("arch_thread_init_tls: TODO\n"); + return B_OK; +} + + +void +arch_thread_dump_info(void* info) +{ + arch_thread* thread = (arch_thread*)info; + + kprintf("\trsp: %p\n", thread->current_stack); + kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp); + kprintf("\tuser_rsp: %p\n", thread->user_rsp); + kprintf("\tfpu_state at %p\n", thread->fpu_state); +} + + +/*! Sets up initial thread context and enters user space +*/ +status_t +arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, + void* args2) +{ + panic("arch_thread_enter_userspace: TODO\n"); + return B_ERROR; +} + + +/*! Sets up the user iframe for invoking a signal handler. + + The function fills in the remaining fields of the given \a signalFrameData, + copies it to the thread's userland stack (the one on which the signal shall + be handled), and sets up the user iframe so that when returning to userland + a wrapper function is executed that calls the user-defined signal handler. + When the signal handler returns, the wrapper function shall call the + "restore signal frame" syscall with the (possibly modified) signal frame + data. + + The following fields of the \a signalFrameData structure still need to be + filled in: + - \c context.uc_stack: The stack currently used by the thread. + - \c context.uc_mcontext: The current userland state of the registers. + - \c syscall_restart_return_value: Architecture specific use. On x86 the + value of eax and edx which are overwritten by the syscall return value. + + Furthermore the function needs to set \c thread->user_signal_context to the + userland pointer to the \c ucontext_t on the user stack. + + \param thread The current thread. + \param action The signal action specified for the signal to be handled. + \param signalFrameData A partially initialized structure of all the data + that need to be copied to userland. + \return \c B_OK on success, another error code, if something goes wrong. +*/ +status_t +arch_setup_signal_frame(Thread* thread, struct sigaction* action, + struct signal_frame_data* signalFrameData) +{ + panic("arch_setup_signal_frame: TODO\n"); + return B_ERROR; +} + + +int64 +arch_restore_signal_frame(struct signal_frame_data* signalFrameData) +{ + panic("arch_restore_signal_frame: TODO\n"); + return B_ERROR; +} diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index ad27ff118e..0fac1a03aa 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -24,6 +24,7 @@ if $(TARGET_ARCH) = x86_64 { int.cpp interrupts.S stubs.cpp + thread.cpp # paging x86_physical_page_mapper_mapped.cpp @@ -43,12 +44,12 @@ if $(TARGET_ARCH) = x86_64 { cpuid.S int.cpp interrupts.S + thread.cpp arch_commpage.cpp arch_debug.cpp arch_real_time_clock.cpp arch_smp.cpp - arch_thread.cpp arch_system_info.cpp arch_user_debugger.cpp apm.cpp @@ -83,6 +84,7 @@ local archGenericSources = arch_elf.cpp arch_int.cpp arch_platform.cpp + arch_thread.cpp arch_timer.cpp arch_vm.cpp arch_vm_translation_map.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 41713b3a57..3640773097 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -91,10 +91,8 @@ extern "C" void x86_reboot(void); // from arch.S void (*gCpuIdleFunc)(void); -#ifndef __x86_64__ void (*gX86SwapFPUFunc)(void* oldState, const void* newState) = x86_noop_swap; bool gHasSSE = false; -#endif static uint32 sCpuRendezvous; static uint32 sCpuRendezvous2; @@ -343,10 +341,8 @@ x86_init_fpu(void) x86_write_cr4(x86_read_cr4() | CR4_OS_FXSR | CR4_OS_XMM_EXCEPTION); x86_write_cr0(x86_read_cr0() & ~(CR0_FPU_EMULATION | CR0_MONITOR_FPU)); -#ifndef __x86_64__ gX86SwapFPUFunc = x86_fxsave_swap; gHasSSE = true; -#endif } @@ -708,7 +704,7 @@ x86_get_double_fault_stack(int32 cpu, size_t* _size) int32 x86_double_fault_get_cpu(void) { - uint32 stack = x86_read_ebp(); + uint32 stack = x86_get_stack_frame(); return (stack - (uint32)sDoubleFaultStacks) / kDoubleFaultStackSize; } #endif @@ -973,13 +969,11 @@ arch_cpu_init_post_modules(kernel_args* args) } -#ifndef __x86_64__ void x86_set_tss_and_kstack(addr_t kstack) { get_cpu_struct()->arch.tss.sp0 = kstack; } -#endif void diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index beedfa3b0d..c8e494cd72 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -363,16 +363,16 @@ print_iframe(struct iframe *frame) { bool isUser = IFRAME_IS_USER(frame); kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, - isUser ? (uint32*)(frame + 1) : &frame->user_esp); + isUser ? (uint32*)(frame + 1) : &frame->user_sp); kprintf(" eax 0x%-9lx ebx 0x%-9lx ecx 0x%-9lx edx 0x%lx\n", - frame->eax, frame->ebx, frame->ecx, frame->edx); + frame->ax, frame->bx, frame->cx, frame->dx); kprintf(" esi 0x%-9lx edi 0x%-9lx ebp 0x%-9lx esp 0x%lx\n", - frame->esi, frame->edi, frame->ebp, frame->esp); - kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->eip, frame->flags); + frame->si, frame->di, frame->bp, frame->sp); + kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->ip, frame->flags); if (isUser) { // from user space - kprintf("user esp 0x%lx", frame->user_esp); + kprintf("user esp 0x%lx", frame->user_sp); } kprintf("\n"); kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, @@ -413,7 +413,7 @@ setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp, thread->cpu->cpu_num); if (registers == NULL) return false; - *_ebp = registers->ebp; + *_ebp = registers->bp; } else { // read %ebp from the thread's stack stored by a pushad *_ebp = thread->arch_info.current_stack.esp[2]; @@ -495,7 +495,7 @@ get_previous_iframe(Thread* thread, struct iframe* frame) if (frame == NULL) return NULL; - return find_previous_iframe(thread, frame->ebp); + return find_previous_iframe(thread, frame->bp); } @@ -532,28 +532,28 @@ find_debug_variable(const char* variableName, bool& settable) return &frame->cs; } else if (strcmp(variableName, "edi") == 0) { settable = true; - return &frame->edi; + return &frame->di; } else if (strcmp(variableName, "esi") == 0) { settable = true; - return &frame->esi; + return &frame->si; } else if (strcmp(variableName, "ebp") == 0) { settable = true; - return &frame->ebp; + return &frame->bp; } else if (strcmp(variableName, "esp") == 0) { settable = true; - return &frame->esp; + return &frame->sp; } else if (strcmp(variableName, "ebx") == 0) { settable = true; - return &frame->ebx; + return &frame->bx; } else if (strcmp(variableName, "edx") == 0) { settable = true; - return &frame->edx; + return &frame->dx; } else if (strcmp(variableName, "ecx") == 0) { settable = true; - return &frame->ecx; + return &frame->cx; } else if (strcmp(variableName, "eax") == 0) { settable = true; - return &frame->eax; + return &frame->ax; } else if (strcmp(variableName, "orig_eax") == 0) { settable = true; return &frame->orig_eax; @@ -562,7 +562,7 @@ find_debug_variable(const char* variableName, bool& settable) return &frame->orig_edx; } else if (strcmp(variableName, "eip") == 0) { settable = true; - return &frame->eip; + return &frame->ip; } else if (strcmp(variableName, "eflags") == 0) { settable = true; return &frame->flags; @@ -571,7 +571,7 @@ find_debug_variable(const char* variableName, bool& settable) if (IFRAME_IS_USER(frame)) { if (strcmp(variableName, "user_esp") == 0) { settable = true; - return &frame->user_esp; + return &frame->user_sp; } else if (strcmp(variableName, "user_ss") == 0) { return &frame->user_ss; } @@ -606,7 +606,7 @@ stack_trace(int argc, char **argv) uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; Thread *thread = NULL; uint32 oldPageDirectory = 0; - uint32 ebp = x86_read_ebp(); + uint32 ebp = x86_get_stack_frame(); int32 num = 0, last = 0; if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL, @@ -641,10 +641,10 @@ stack_trace(int argc, char **argv) struct iframe *frame = (struct iframe *)ebp; print_iframe(frame); - print_stack_frame(thread, frame->eip, ebp, frame->ebp, callIndex, + print_stack_frame(thread, frame->ip, ebp, frame->bp, callIndex, demangle); - ebp = frame->ebp; + ebp = frame->bp; } else { addr_t eip, nextEbp; @@ -760,7 +760,7 @@ show_call(int argc, char **argv) Thread *thread = NULL; uint32 oldPageDirectory = 0; - addr_t ebp = x86_read_ebp(); + addr_t ebp = x86_get_stack_frame(); int32 argCount = 0; if (argc >= 2 && argv[argc - 1][0] == '-') { @@ -804,9 +804,9 @@ show_call(int argc, char **argv) struct iframe *frame = (struct iframe *)ebp; if (index == callIndex) - print_call(thread, frame->eip, ebp, frame->ebp, argCount); + print_call(thread, frame->ip, ebp, frame->bp, argCount); - ebp = frame->ebp; + ebp = frame->bp; } else { addr_t eip, nextEbp; @@ -871,7 +871,7 @@ dump_iframes(int argc, char **argv) DebuggedThreadSetter threadSetter(thread); - struct iframe* frame = find_previous_iframe(thread, x86_read_ebp()); + struct iframe* frame = find_previous_iframe(thread, x86_get_stack_frame()); while (frame != NULL) { print_iframe(frame); frame = get_previous_iframe(thread, frame); @@ -965,8 +965,8 @@ void arch_debug_save_registers(struct arch_debug_registers* registers) { // get the caller's frame pointer - stack_frame* frame = (stack_frame*)x86_read_ebp(); - registers->ebp = (addr_t)frame->previous; + stack_frame* frame = (stack_frame*)x86_get_stack_frame(); + registers->bp = (addr_t)frame->previous; } @@ -985,7 +985,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol, addr_t ebp; if (thread == thread_get_current_thread()) - ebp = x86_read_ebp(); + ebp = x86_get_stack_frame(); else { if (thread->state == B_THREAD_RUNNING) { // The thread is currently running on another CPU. @@ -995,7 +995,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol, thread->cpu->cpu_num); if (registers == NULL) return false; - ebp = registers->ebp; + ebp = registers->bp; } else { // thread not running ebp = thread->arch_info.current_stack.esp[2]; @@ -1009,10 +1009,10 @@ arch_debug_contains_call(Thread *thread, const char *symbol, if (is_iframe(thread, ebp)) { struct iframe *frame = (struct iframe *)ebp; - if (is_calling(thread, frame->eip, symbol, start, end)) + if (is_calling(thread, frame->ip, symbol, start, end)) return true; - ebp = frame->ebp; + ebp = frame->bp; } else { addr_t eip, nextEbp; @@ -1037,7 +1037,7 @@ arch_debug_contains_call(Thread *thread, const char *symbol, void * arch_debug_get_caller(void) { - struct stack_frame *frame = (struct stack_frame *)x86_read_ebp(); + struct stack_frame *frame = (struct stack_frame *)x86_get_stack_frame(); return (void *)frame->previous->return_address; } @@ -1064,7 +1064,7 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, Thread* thread = thread_get_current_thread(); int32 count = 0; - addr_t ebp = x86_read_ebp(); + addr_t ebp = x86_get_stack_frame(); bool onKernelStack = true; while (ebp != 0 && count < maxCount) { @@ -1078,8 +1078,8 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, if (onKernelStack && is_iframe(thread, ebp)) { struct iframe *frame = (struct iframe*)ebp; - eip = frame->eip; - nextEbp = frame->ebp; + eip = frame->ip; + nextEbp = frame->bp; if (skipIframes > 0) { if (--skipIframes == 0) @@ -1119,7 +1119,7 @@ arch_debug_get_interrupt_pc(bool* _isSyscall) if (_isSyscall != NULL) *_isSyscall = frame->vector == 99; - return (void*)(addr_t)frame->eip; + return (void*)(addr_t)frame->ip; } @@ -1199,9 +1199,9 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) // gdb wants the register dump in *big endian* format. static const int32 kRegisterCount = 14; uint32 registers[kRegisterCount] = { - frame->eax, frame->ebx, frame->ecx, frame->edx, - frame->esp, frame->ebp, frame->esi, frame->edi, - frame->eip, frame->flags, + frame->ax, frame->bx, frame->cx, frame->dx, + frame->sp, frame->bp, frame->si, frame->di, + frame->ip, frame->flags, frame->cs, frame->ds, frame->ds, frame->es // assume ss == ds }; diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 9bec1d7743..3fdee860d3 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -89,6 +89,7 @@ hardware_interrupt(struct iframe* frame) callback(data); } #else + return; panic("implement me"); #endif } @@ -159,7 +160,7 @@ arch_int_init_io(kernel_args* args) ioapic_init(args); msi_init(); #else - panic("implement me"); + //panic("implement me"); #endif return B_OK; } diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index da8e47d739..d0a1769a43 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -11,96 +11,36 @@ #include -#include #include #include -#include #include #include #include #include #include -#include -#include -#include #include #include #include "paging/X86PagingStructures.h" #include "paging/X86VMTranslationMap.h" -#include "x86_signals.h" #include "x86_syscalls.h" -//#define TRACE_ARCH_THREAD -#ifdef TRACE_ARCH_THREAD -# define TRACE(x) dprintf x -#else -# define TRACE(x) ; -#endif - - -#ifdef SYSCALL_TRACING - -namespace SyscallTracing { - -class RestartSyscall : public AbstractTraceEntry { - public: - RestartSyscall() - { - Initialized(); - } - - virtual void AddDump(TraceOutput& out) - { - out.Print("syscall restart"); - } -}; - -} - -# define TSYSCALL(x) new(std::nothrow) SyscallTracing::x - -#else -# define TSYSCALL(x) -#endif // SYSCALL_TRACING - - // from arch_interrupts.S extern "C" void x86_return_to_userland(iframe* frame); -// from arch_cpu.c +// from arch_cpu.cpp extern void (*gX86SwapFPUFunc)(void *oldState, const void *newState); -extern bool gHasSSE; - -static struct arch_thread sInitialState _ALIGNED(16); - // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it -status_t -arch_thread_init(struct kernel_args *args) -{ - // save one global valid FPU state; it will be copied in the arch dependent - // part of each new thread - - asm volatile ("clts; fninit; fnclex;"); - if (gHasSSE) - x86_fxsave(sInitialState.fpu_state); - else - x86_fnsave(sInitialState.fpu_state); - - return B_OK; -} - - -static struct iframe * -find_previous_iframe(Thread *thread, addr_t frame) +static struct iframe* +find_previous_iframe(Thread* thread, addr_t frame) { // iterate backwards through the stack frames, until we hit an iframe while (frame >= thread->kernel_stack_base && frame < thread->kernel_stack_top) { addr_t previousFrame = *(addr_t*)frame; - if ((previousFrame & ~IFRAME_TYPE_MASK) == 0) { + if ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0) { if (previousFrame == 0) return NULL; return (struct iframe*)frame; @@ -119,7 +59,7 @@ get_previous_iframe(struct iframe* frame) if (frame == NULL) return NULL; - return find_previous_iframe(thread_get_current_thread(), frame->ebp); + return find_previous_iframe(thread_get_current_thread(), frame->bp); } @@ -132,39 +72,8 @@ get_previous_iframe(struct iframe* frame) static struct iframe* get_current_iframe(void) { - return find_previous_iframe(thread_get_current_thread(), x86_read_ebp()); -} - - -static inline void -set_fs_register(uint32 segment) -{ - asm("movl %0,%%fs" :: "r" (segment)); -} - - -/*! Returns to the userland environment given by \a frame for a thread not - having been userland before. - - Before returning to userland all potentially necessary kernel exit work is - done. - - \param thread The current thread. - \param frame The iframe defining the userland environment. Must point to a - location somewhere on the caller's stack (e.g. a local variable). -*/ -static void -initial_return_to_userland(Thread* thread, iframe* frame) -{ - // disable interrupts and set up CPU specifics for this thread - disable_interrupts(); - - x86_set_tss_and_kstack(thread->kernel_stack_top); - x86_set_tls_context(thread); - x86_set_syscall_stack(thread->kernel_stack_top); - - // return to userland - x86_return_to_userland(frame); + return find_previous_iframe(thread_get_current_thread(), + x86_get_stack_frame()); } @@ -175,7 +84,7 @@ initial_return_to_userland(Thread* thread, iframe* frame) \return The iframe, or \c NULL, if there is no such iframe (e.g. when the thread is a kernel thread). */ -struct iframe * +struct iframe* x86_get_user_iframe(void) { struct iframe* frame = get_current_iframe(); @@ -193,17 +102,21 @@ x86_get_user_iframe(void) /*! \brief Like x86_get_user_iframe(), just for the given thread. The thread must not be running and the threads spinlock must be held. */ -struct iframe * +struct iframe* x86_get_thread_user_iframe(Thread *thread) { if (thread->state == B_THREAD_RUNNING) return NULL; - // read %ebp from the thread's stack stored by a pushad - addr_t ebp = thread->arch_info.current_stack.esp[2]; + // Read frame pointer from the thread's stack. +#ifdef __x86_64__ + addr_t bp = thread->arch_info.current_stack[1]; +#else + addr_t bp = thread->arch_info.current_stack.esp[2]; +#endif // find the user iframe - struct iframe *frame = find_previous_iframe(thread, ebp); + struct iframe* frame = find_previous_iframe(thread, bp); while (frame != NULL) { if (IFRAME_IS_USER(frame)) @@ -215,14 +128,14 @@ x86_get_thread_user_iframe(Thread *thread) } -struct iframe * +struct iframe* x86_get_current_iframe(void) { return get_current_iframe(); } -uint32 +phys_addr_t x86_next_page_directory(Thread *from, Thread *to) { VMAddressSpace* toAddressSpace = to->team->address_space; @@ -239,47 +152,45 @@ x86_next_page_directory(Thread *from, Thread *to) } +/*! Returns to the userland environment given by \a frame for a thread not + having been userland before. + + Before returning to userland all potentially necessary kernel exit work is + done. + + \param thread The current thread. + \param frame The iframe defining the userland environment. Must point to a + location somewhere on the caller's stack (e.g. a local variable). +*/ void -x86_restart_syscall(struct iframe* frame) +x86_initial_return_to_userland(Thread* thread, iframe* frame) { - Thread* thread = thread_get_current_thread(); + // disable interrupts and set up CPU specifics for this thread + disable_interrupts(); - atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); - atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); + x86_set_tss_and_kstack(thread->kernel_stack_top); + x86_set_tls_context(thread); + x86_set_syscall_stack(thread->kernel_stack_top); - frame->eax = frame->orig_eax; - frame->edx = frame->orig_edx; - frame->eip -= 2; - // undoes the "int $99"/"sysenter"/"syscall" instruction - // (so that it'll be executed again) - - TSYSCALL(RestartSyscall()); + // return to userland + x86_return_to_userland(frame); } -void -x86_set_tls_context(Thread *thread) -{ - int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT; - - set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage); - set_fs_register((entry << 3) | DPL_USER); -} - - -static uint8* -get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action) +uint8* +x86_get_signal_stack(Thread* thread, struct iframe* frame, + struct sigaction* action) { // use the alternate signal stack if we should and can if (thread->signal_stack_enabled && (action->sa_flags & SA_ONSTACK) != 0 - && (frame->user_esp < thread->signal_stack_base - || frame->user_esp >= thread->signal_stack_base + && (frame->user_sp < thread->signal_stack_base + || frame->user_sp >= thread->signal_stack_base + thread->signal_stack_size)) { return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); } - return (uint8*)frame->user_esp; + return (uint8*)frame->user_sp; } @@ -287,84 +198,14 @@ get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action) status_t -arch_team_init_team_struct(Team *p, bool kernel) +arch_team_init_team_struct(Team* p, bool kernel) { return B_OK; } -status_t -arch_thread_init_thread_struct(Thread *thread) -{ - // set up an initial state (stack & fpu) - memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread)); - return B_OK; -} - - -/*! Prepares the given thread's kernel stack for executing its entry function. - - \param thread The thread. - \param stack The usable bottom of the thread's kernel stack. - \param stackTop The usable top of the thread's kernel stack. - \param function The entry function the thread shall execute. - \param data Pointer to be passed to the entry function. -*/ void -arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, - void (*function)(void*), const void* data) -{ - addr_t* stackTop = (addr_t*)_stackTop; - - TRACE(("arch_thread_init_kthread_stack: stack top %p, function %, data: " - "%p\n", stackTop, function, data)); - - // push the function argument, a pointer to the data - *--stackTop = (addr_t)data; - - // push a dummy return address for the function - *--stackTop = 0; - - // push the function address -- that's the return address used after the - // context switch - *--stackTop = (addr_t)function; - - // simulate pushad as done by x86_context_switch() - for (int i = 0; i < 8; i++) - *--stackTop = 0; - - // save the stack position - thread->arch_info.current_stack.esp = stackTop; - thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG; -} - - -/** Initializes the user-space TLS local storage pointer in - * the thread structure, and the reserved TLS slots. - * - * Is called from _create_user_thread_kentry(). - */ - -status_t -arch_thread_init_tls(Thread *thread) -{ - uint32 tls[TLS_USER_THREAD_SLOT + 1]; - - thread->user_local_storage = thread->user_stack_base - + thread->user_stack_size; - - // initialize default TLS fields - memset(tls, 0, sizeof(tls)); - tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; - tls[TLS_THREAD_ID_SLOT] = thread->id; - tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; - - return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls)); -} - - -void -arch_thread_context_switch(Thread *from, Thread *to) +arch_thread_context_switch(Thread* from, Thread* to) { x86_set_tss_and_kstack(to->kernel_stack_top); x86_set_syscall_stack(to->kernel_stack_top); @@ -395,7 +236,7 @@ arch_thread_context_switch(Thread *from, Thread *to) cpuData->arch.active_paging_structures = toPagingStructures; // set the page directory, if it changes - uint32 newPageDirectory = toPagingStructures->pgdir_phys; + addr_t newPageDirectory = toPagingStructures->pgdir_phys; if (newPageDirectory != activePagingStructures->pgdir_phys) x86_swap_pgdir(newPageDirectory); @@ -408,225 +249,31 @@ arch_thread_context_switch(Thread *from, Thread *to) } -void -arch_thread_dump_info(void *info) -{ - struct arch_thread *at = (struct arch_thread *)info; - - kprintf("\tesp: %p\n", at->current_stack.esp); - kprintf("\tss: %p\n", at->current_stack.ss); - kprintf("\tfpu_state at %p\n", at->fpu_state); -} - - -/*! Sets up initial thread context and enters user space -*/ -status_t -arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, - void* args2) -{ - addr_t stackTop = thread->user_stack_base + thread->user_stack_size; - uint32 codeSize = (addr_t)x86_end_userspace_thread_exit - - (addr_t)x86_userspace_thread_exit; - uint32 args[3]; - - TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, " - "ustack_top 0x%lx\n", entry, args1, args2, stackTop)); - - // copy the little stub that calls exit_thread() when the thread entry - // function returns, as well as the arguments of the entry function - stackTop -= codeSize; - - if (user_memcpy((void *)stackTop, (const void *)&x86_userspace_thread_exit, codeSize) < B_OK) - return B_BAD_ADDRESS; - - args[0] = stackTop; - args[1] = (uint32)args1; - args[2] = (uint32)args2; - stackTop -= sizeof(args); - - if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) - return B_BAD_ADDRESS; - - // prepare the user iframe - iframe frame = {}; - frame.type = IFRAME_TYPE_SYSCALL; - frame.gs = USER_DATA_SEG; - // frame.fs not used, we call x86_set_tls_context() on context switch - frame.es = USER_DATA_SEG; - frame.ds = USER_DATA_SEG; - frame.eip = entry; - frame.cs = USER_CODE_SEG; - frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT - | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); - frame.user_esp = stackTop; - frame.user_ss = USER_DATA_SEG; - - // return to userland - initial_return_to_userland(thread, &frame); - - return B_OK; - // never gets here -} - - bool arch_on_signal_stack(Thread *thread) { - struct iframe *frame = get_current_iframe(); + struct iframe* frame = get_current_iframe(); - return frame->user_esp >= thread->signal_stack_base - && frame->user_esp < thread->signal_stack_base + return frame->user_sp >= thread->signal_stack_base + && frame->user_sp < thread->signal_stack_base + thread->signal_stack_size; } -/*! Sets up the user iframe for invoking a signal handler. - - The function fills in the remaining fields of the given \a signalFrameData, - copies it to the thread's userland stack (the one on which the signal shall - be handled), and sets up the user iframe so that when returning to userland - a wrapper function is executed that calls the user-defined signal handler. - When the signal handler returns, the wrapper function shall call the - "restore signal frame" syscall with the (possibly modified) signal frame - data. - - The following fields of the \a signalFrameData structure still need to be - filled in: - - \c context.uc_stack: The stack currently used by the thread. - - \c context.uc_mcontext: The current userland state of the registers. - - \c syscall_restart_return_value: Architecture specific use. On x86 the - value of eax and edx which are overwritten by the syscall return value. - - Furthermore the function needs to set \c thread->user_signal_context to the - userland pointer to the \c ucontext_t on the user stack. - - \param thread The current thread. - \param action The signal action specified for the signal to be handled. - \param signalFrameData A partially initialized structure of all the data - that need to be copied to userland. - \return \c B_OK on success, another error code, if something goes wrong. +/*! Saves everything needed to restore the frame in the child fork in the + arch_fork_arg structure to be passed to arch_restore_fork_frame(). + Also makes sure to return the right value. */ -status_t -arch_setup_signal_frame(Thread* thread, struct sigaction* action, - struct signal_frame_data* signalFrameData) -{ - struct iframe *frame = get_current_iframe(); - if (!IFRAME_IS_USER(frame)) { - panic("arch_setup_signal_frame(): No user iframe!"); - return B_BAD_VALUE; - } - - // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since they - // had the same signal number. - if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0 - && signalFrameData->info.si_signo == SIGBUS) { - signalFrameData->info.si_signo = SIGSEGV; - } - - // store the register state in signalFrameData->context.uc_mcontext - signalFrameData->context.uc_mcontext.eip = frame->eip; - signalFrameData->context.uc_mcontext.eflags = frame->flags; - signalFrameData->context.uc_mcontext.eax = frame->eax; - signalFrameData->context.uc_mcontext.ecx = frame->ecx; - signalFrameData->context.uc_mcontext.edx = frame->edx; - signalFrameData->context.uc_mcontext.ebp = frame->ebp; - signalFrameData->context.uc_mcontext.esp = frame->user_esp; - signalFrameData->context.uc_mcontext.edi = frame->edi; - signalFrameData->context.uc_mcontext.esi = frame->esi; - signalFrameData->context.uc_mcontext.ebx = frame->ebx; - x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); - - // fill in signalFrameData->context.uc_stack - signal_get_user_stack(frame->user_esp, &signalFrameData->context.uc_stack); - - // store orig_eax/orig_edx in syscall_restart_return_value - signalFrameData->syscall_restart_return_value - = (uint64)frame->orig_edx << 32 | frame->orig_eax; - - // get the stack to use -- that's either the current one or a special signal - // stack - uint8* userStack = get_signal_stack(thread, frame, action); - - // copy the signal frame data onto the stack - userStack -= sizeof(*signalFrameData); - signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; - if (user_memcpy(userSignalFrameData, signalFrameData, - sizeof(*signalFrameData)) != B_OK) { - return B_BAD_ADDRESS; - } - - // prepare the user stack frame for a function call to the signal handler - // wrapper function - uint32 stackFrame[2] = { - frame->eip, // return address - (addr_t)userSignalFrameData, // parameter: pointer to signal frame data - }; - - userStack -= sizeof(stackFrame); - if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) - return B_BAD_ADDRESS; - - // Update Thread::user_signal_context, now that everything seems to have - // gone fine. - thread->user_signal_context = &userSignalFrameData->context; - - // Adjust the iframe's esp and eip, so that the thread will continue with - // the prepared stack, executing the signal handler wrapper function. - frame->user_esp = (addr_t)userStack; - frame->eip = x86_get_user_signal_handler_wrapper( - (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0); - - return B_OK; -} - - -int64 -arch_restore_signal_frame(struct signal_frame_data* signalFrameData) -{ - struct iframe* frame = get_current_iframe(); - - TRACE(("### arch_restore_signal_frame: entry\n")); - - frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value; - frame->orig_edx - = (uint32)(signalFrameData->syscall_restart_return_value >> 32); - - frame->eip = signalFrameData->context.uc_mcontext.eip; - frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS) - | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); - frame->eax = signalFrameData->context.uc_mcontext.eax; - frame->ecx = signalFrameData->context.uc_mcontext.ecx; - frame->edx = signalFrameData->context.uc_mcontext.edx; - frame->ebp = signalFrameData->context.uc_mcontext.ebp; - frame->user_esp = signalFrameData->context.uc_mcontext.esp; - frame->edi = signalFrameData->context.uc_mcontext.edi; - frame->esi = signalFrameData->context.uc_mcontext.esi; - frame->ebx = signalFrameData->context.uc_mcontext.ebx; - - x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); - - TRACE(("### arch_restore_signal_frame: exit\n")); - - return (int64)frame->eax | ((int64)frame->edx << 32); -} - - -/** Saves everything needed to restore the frame in the child fork in the - * arch_fork_arg structure to be passed to arch_restore_fork_frame(). - * Also makes sure to return the right value. - */ - void -arch_store_fork_frame(struct arch_fork_arg *arg) +arch_store_fork_frame(struct arch_fork_arg* arg) { - struct iframe *frame = get_current_iframe(); + struct iframe* frame = x86_get_current_iframe(); // we need to copy the threads current iframe arg->iframe = *frame; // we also want fork() to return 0 for the child - arg->iframe.eax = 0; + arg->iframe.ax = 0; } @@ -644,13 +291,5 @@ arch_store_fork_frame(struct arch_fork_arg *arg) void arch_restore_fork_frame(struct arch_fork_arg* arg) { - initial_return_to_userland(thread_get_current_thread(), &arg->iframe); -} - - -void -arch_syscall_64_bit_return_value(void) -{ - Thread* thread = thread_get_current_thread(); - atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); + x86_initial_return_to_userland(thread_get_current_thread(), &arg->iframe); } diff --git a/src/system/kernel/arch/x86/arch_user_debugger.cpp b/src/system/kernel/arch/x86/arch_user_debugger.cpp index 99e2b83218..4a5d232bec 100644 --- a/src/system/kernel/arch/x86/arch_user_debugger.cpp +++ b/src/system/kernel/arch/x86/arch_user_debugger.cpp @@ -75,20 +75,20 @@ get_iframe_registers(struct iframe *frame, debug_cpu_state *cpuState) cpuState->fs = frame->fs; cpuState->es = frame->es; cpuState->ds = frame->ds; - cpuState->edi = frame->edi; - cpuState->esi = frame->esi; - cpuState->ebp = frame->ebp; - cpuState->esp = frame->esp; - cpuState->ebx = frame->ebx; + cpuState->edi = frame->di; + cpuState->esi = frame->si; + cpuState->ebp = frame->bp; + cpuState->esp = frame->sp; + cpuState->ebx = frame->bx; cpuState->edx = frame->orig_edx; - cpuState->ecx = frame->ecx; + cpuState->ecx = frame->cx; cpuState->eax = frame->orig_eax; cpuState->vector = frame->vector; cpuState->error_code = frame->error_code; - cpuState->eip = frame->eip; + cpuState->eip = frame->ip; cpuState->cs = frame->cs; cpuState->eflags = frame->flags; - cpuState->user_esp = frame->user_esp; + cpuState->user_esp = frame->user_sp; cpuState->user_ss = frame->user_ss; } @@ -606,21 +606,21 @@ arch_set_debug_cpu_state(const debug_cpu_state *cpuState) // frame->fs = cpuState->fs; // frame->es = cpuState->es; // frame->ds = cpuState->ds; - frame->edi = cpuState->edi; - frame->esi = cpuState->esi; - frame->ebp = cpuState->ebp; + frame->di = cpuState->edi; + frame->si = cpuState->esi; + frame->bp = cpuState->ebp; // frame->esp = cpuState->esp; - frame->ebx = cpuState->ebx; - frame->edx = cpuState->edx; - frame->ecx = cpuState->ecx; - frame->eax = cpuState->eax; + frame->bx = cpuState->ebx; + frame->dx = cpuState->edx; + frame->cx = cpuState->ecx; + frame->ax = cpuState->eax; // frame->vector = cpuState->vector; // frame->error_code = cpuState->error_code; - frame->eip = cpuState->eip; + frame->ip = cpuState->eip; // frame->cs = cpuState->cs; frame->flags = (frame->flags & ~X86_EFLAGS_USER_SETTABLE_FLAGS) | (cpuState->eflags & X86_EFLAGS_USER_SETTABLE_FLAGS); - frame->user_esp = cpuState->user_esp; + frame->user_sp = cpuState->user_esp; // frame->user_ss = cpuState->user_ss; } } @@ -977,7 +977,7 @@ x86_handle_breakpoint_exception(struct iframe *frame) TRACE(("x86_handle_breakpoint_exception()\n")); // reset eip to the int3 instruction - frame->eip--; + frame->ip--; if (!IFRAME_IS_USER(frame)) { panic("breakpoint exception in kernel mode"); diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index 679f852a60..469c4f71d4 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -45,20 +45,23 @@ dummy() DEFINE_OFFSET_MACRO(THREAD, Thread, fault_handler); #ifdef __x86_64__ - // struct iframe - DEFINE_SIZEOF_MACRO(IFRAME, iframe); - DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); -#else + // struct arch_thread + DEFINE_OFFSET_MACRO(ARCH_THREAD, arch_thread, syscall_rsp); + DEFINE_OFFSET_MACRO(ARCH_THREAD, arch_thread, user_rsp); + DEFINE_OFFSET_MACRO(ARCH_THREAD, arch_thread, current_stack); +#endif + // struct iframe DEFINE_SIZEOF_MACRO(IFRAME, iframe); DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); - DEFINE_OFFSET_MACRO(IFRAME, iframe, eax); - DEFINE_OFFSET_MACRO(IFRAME, iframe, edx); - DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); + DEFINE_OFFSET_MACRO(IFRAME, iframe, ax); + DEFINE_OFFSET_MACRO(IFRAME, iframe, dx); DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); - DEFINE_OFFSET_MACRO(IFRAME, iframe, eip); + DEFINE_OFFSET_MACRO(IFRAME, iframe, ip); DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); - DEFINE_OFFSET_MACRO(IFRAME, iframe, user_esp); + DEFINE_OFFSET_MACRO(IFRAME, iframe, user_sp); +#ifdef __INTEL__ + DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); // struct vm86_iframe DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); diff --git a/src/system/kernel/arch/x86/x86_syscalls.h b/src/system/kernel/arch/x86/x86_syscalls.h index db0dd75f33..788e01a253 100644 --- a/src/system/kernel/arch/x86/x86_syscalls.h +++ b/src/system/kernel/arch/x86/x86_syscalls.h @@ -18,8 +18,11 @@ void x86_initialize_commpage_syscall(); static inline void x86_set_syscall_stack(addr_t stackTop) { + // TODO: x86_64 +#ifndef __x86_64__ if (gX86SetSyscallStack != NULL) gX86SetSyscallStack(stackTop); +#endif } From c8049a88a3ea4a5d8b4144f7f053d712815b75ce Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 17:42:34 +0100 Subject: [PATCH 090/273] Enabled hardware interrupt handler, timers now work and threads are preempted. --- src/system/kernel/arch/x86/arch_int.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 3fdee860d3..a7ecd656b1 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -45,7 +45,6 @@ static const interrupt_controller* sCurrentPIC = NULL; void hardware_interrupt(struct iframe* frame) { -#ifndef __x86_64__ int32 vector = frame->vector - ARCH_INTERRUPT_BASE; bool levelTriggered = false; Thread* thread = thread_get_current_thread(); @@ -88,10 +87,6 @@ hardware_interrupt(struct iframe* frame) callback(data); } -#else - return; - panic("implement me"); -#endif } @@ -156,11 +151,10 @@ arch_int_are_interrupts_enabled(void) status_t arch_int_init_io(kernel_args* args) { + // TODO x86_64 #ifndef __x86_64__ ioapic_init(args); msi_init(); -#else - //panic("implement me"); #endif return B_OK; } From 5670b0a8e4fe8e5504b2e57a958e1590f6024406 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 9 Jul 2012 19:18:09 +0100 Subject: [PATCH 091/273] Moved the 32-bit page fault handler to arch_int.cpp, use it for x86_64. A proper page fault handler was required for areas that were not locked into the kernel address space. This enables the boot process to get up to the point of trying to find the boot volume. --- headers/private/kernel/arch/x86/arch_cpu.h | 8 ++- src/system/kernel/arch/x86/32/int.cpp | 83 +--------------------- src/system/kernel/arch/x86/64/int.cpp | 12 +--- src/system/kernel/arch/x86/arch_cpu.cpp | 4 +- src/system/kernel/arch/x86/arch_int.cpp | 83 ++++++++++++++++++++++ 5 files changed, 91 insertions(+), 99 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 32f0129c31..a9100c77c5 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -405,8 +405,9 @@ void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos, void x86_init_fpu(); bool x86_check_feature(uint32 feature, enum x86_feature_type type); void* x86_get_double_fault_stack(int32 cpu, size_t* _size); -void x86_double_fault_exception(struct iframe* frame); -void x86_page_fault_exception_double_fault(struct iframe* frame); +int32 x86_double_fault_get_cpu(void); + +void x86_page_fault_exception(struct iframe* iframe); #ifndef __x86_64__ @@ -414,7 +415,8 @@ void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); void x86_set_task_gate(int32 cpu, int32 n, int32 segment); -int32 x86_double_fault_get_cpu(void); +void x86_double_fault_exception(struct iframe* frame); +void x86_page_fault_exception_double_fault(struct iframe* frame); #endif diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index acfc11778b..c49ec88d0a 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -346,87 +346,6 @@ x86_page_fault_exception_double_fault(struct iframe* frame) } -static void -page_fault_exception(struct iframe* frame) -{ - Thread *thread = thread_get_current_thread(); - addr_t cr2 = x86_read_cr2(); - addr_t newip; - - if (debug_debugger_running()) { - // If this CPU or this thread has a fault handler, we're allowed to be - // here. - if (thread != NULL) { - cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; - if (cpu->fault_handler != 0) { - debug_set_page_fault_info(cr2, frame->ip, - (frame->error_code & 0x2) != 0 - ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->ip = cpu->fault_handler; - frame->bp = cpu->fault_handler_stack_pointer; - return; - } - - if (thread->fault_handler != 0) { - kprintf("ERROR: thread::fault_handler used in kernel " - "debugger!\n"); - debug_set_page_fault_info(cr2, frame->ip, - (frame->error_code & 0x2) != 0 - ? DEBUG_PAGE_FAULT_WRITE : 0); - frame->ip = thread->fault_handler; - return; - } - } - - // otherwise, not really - panic("page fault in debugger without fault handler! Touching " - "address %p from eip %p\n", (void *)cr2, (void *)frame->ip); - return; - } else if ((frame->flags & 0x200) == 0) { - // interrupts disabled - - // If a page fault handler is installed, we're allowed to be here. - // TODO: Now we are generally allowing user_memcpy() with interrupts - // disabled, which in most cases is a bug. We should add some thread - // flag allowing to explicitly indicate that this handling is desired. - if (thread && thread->fault_handler != 0) { - if (frame->ip != thread->fault_handler) { - frame->ip = thread->fault_handler; - return; - } - - // The fault happened at the fault handler address. This is a - // certain infinite loop. - panic("page fault, interrupts disabled, fault handler loop. " - "Touching address %p from eip %p\n", (void*)cr2, - (void*)frame->ip); - } - - // If we are not running the kernel startup the page fault was not - // allowed to happen and we must panic. - panic("page fault, but interrupts were disabled. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->ip); - return; - } else if (thread != NULL && thread->page_faults_allowed < 1) { - panic("page fault not allowed at this place. Touching address " - "%p from eip %p\n", (void *)cr2, (void *)frame->ip); - return; - } - - enable_interrupts(); - - vm_page_fault(cr2, frame->ip, - (frame->error_code & 0x2) != 0, // write access - (frame->error_code & 0x4) != 0, // userland - &newip); - if (newip != 0) { - // the page fault handler wants us to modify the iframe to set the - // IP the cpu will return to to be this ip - frame->ip = newip; - } -} - - status_t arch_int_init(struct kernel_args *args) { @@ -720,7 +639,7 @@ arch_int_init(struct kernel_args *args) table[11] = fatal_exception; // Segment Not Present (#NP) table[12] = fatal_exception; // Stack Fault Exception (#SS) table[13] = unexpected_exception; // General Protection Exception (#GP) - table[14] = page_fault_exception; // Page-Fault Exception (#PF) + table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) table[17] = unexpected_exception; // Alignment Check Exception (#AC) table[18] = fatal_exception; // Machine-Check Exception (#MC) diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index 6117171e30..f0cfb800e6 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -96,16 +96,6 @@ unexpected_exception(iframe* frame) } -static void -page_fault_exception(iframe* frame) -{ - addr_t cr2 = x86_read_cr2(); - - panic("page fault exception at ip %#lx on %#lx, error code %#lx\n", - frame->ip, cr2, frame->error_code); -} - - /*! Returns the virtual IDT address for CPU \a cpu. */ void* x86_get_idt(int32 cpu) @@ -164,7 +154,7 @@ arch_int_init(kernel_args* args) table[11] = fatal_exception; // Segment Not Present (#NP) table[12] = fatal_exception; // Stack Fault Exception (#SS) table[13] = unexpected_exception; // General Protection Exception (#GP) - table[14] = page_fault_exception; // Page-Fault Exception (#PF) + table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) table[17] = unexpected_exception; // Alignment Check Exception (#AC) table[18] = fatal_exception; // Machine-Check Exception (#MC) diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 3640773097..10c94f6de2 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -697,7 +697,6 @@ x86_get_double_fault_stack(int32 cpu, size_t* _size) } -#ifndef __x86_64__ /*! Returns the index of the current CPU. Can only be called from the double fault handler. */ @@ -705,9 +704,8 @@ int32 x86_double_fault_get_cpu(void) { uint32 stack = x86_get_stack_frame(); - return (stack - (uint32)sDoubleFaultStacks) / kDoubleFaultStackSize; + return (stack - (addr_t)sDoubleFaultStacks) / kDoubleFaultStackSize; } -#endif // #pragma mark - diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index a7ecd656b1..21dedb3a67 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include @@ -90,6 +92,87 @@ hardware_interrupt(struct iframe* frame) } +void +x86_page_fault_exception(struct iframe* frame) +{ + Thread* thread = thread_get_current_thread(); + addr_t cr2 = x86_read_cr2(); + addr_t newip; + + if (debug_debugger_running()) { + // If this CPU or this thread has a fault handler, we're allowed to be + // here. + if (thread != NULL) { + cpu_ent* cpu = &gCPU[smp_get_current_cpu()]; + if (cpu->fault_handler != 0) { + debug_set_page_fault_info(cr2, frame->ip, + (frame->error_code & 0x2) != 0 + ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->ip = cpu->fault_handler; + frame->bp = cpu->fault_handler_stack_pointer; + return; + } + + if (thread->fault_handler != 0) { + kprintf("ERROR: thread::fault_handler used in kernel " + "debugger!\n"); + debug_set_page_fault_info(cr2, frame->ip, + (frame->error_code & 0x2) != 0 + ? DEBUG_PAGE_FAULT_WRITE : 0); + frame->ip = thread->fault_handler; + return; + } + } + + // otherwise, not really + panic("page fault in debugger without fault handler! Touching " + "address %p from ip %p\n", (void*)cr2, (void*)frame->ip); + return; + } else if ((frame->flags & 0x200) == 0) { + // interrupts disabled + + // If a page fault handler is installed, we're allowed to be here. + // TODO: Now we are generally allowing user_memcpy() with interrupts + // disabled, which in most cases is a bug. We should add some thread + // flag allowing to explicitly indicate that this handling is desired. + if (thread && thread->fault_handler != 0) { + if (frame->ip != thread->fault_handler) { + frame->ip = thread->fault_handler; + return; + } + + // The fault happened at the fault handler address. This is a + // certain infinite loop. + panic("page fault, interrupts disabled, fault handler loop. " + "Touching address %p from ip %p\n", (void*)cr2, + (void*)frame->ip); + } + + // If we are not running the kernel startup the page fault was not + // allowed to happen and we must panic. + panic("page fault, but interrupts were disabled. Touching address " + "%p from ip %p\n", (void*)cr2, (void*)frame->ip); + return; + } else if (thread != NULL && thread->page_faults_allowed < 1) { + panic("page fault not allowed at this place. Touching address " + "%p from ip %p\n", (void*)cr2, (void*)frame->ip); + return; + } + + enable_interrupts(); + + vm_page_fault(cr2, frame->ip, + (frame->error_code & 0x2) != 0, // write access + (frame->error_code & 0x4) != 0, // userland + &newip); + if (newip != 0) { + // the page fault handler wants us to modify the iframe to set the + // IP the cpu will return to this ip + frame->ip = newip; + } +} + + // #pragma mark - From 609b308e64d28acbcac1edde134b427f648914a4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 11 Jul 2012 12:23:18 +0100 Subject: [PATCH 092/273] Return B_NOT_SUPPORTED for shutdown if ACPI is unavailable (no APM on x86_64). --- src/system/kernel/arch/x86/arch_cpu.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 10c94f6de2..9fe0d79075 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1026,11 +1026,13 @@ arch_cpu_shutdown(bool rebootSystem) if (acpi_shutdown(rebootSystem) == B_OK) return B_OK; - // TODO x86_64 -#ifndef __x86_64 - if (!rebootSystem) + if (!rebootSystem) { +#ifndef __x86_64__ return apm_shutdown(); +#else + return B_NOT_SUPPORTED; #endif + } cpu_status state = disable_interrupts(); From d776fd53f7fdf12f297838ca476948bc7083c82a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 11 Jul 2012 14:19:19 +0100 Subject: [PATCH 093/273] Implemented arch_cpu_user_*() for x86_64, based on the x86 versions. --- src/system/kernel/arch/x86/64/arch.S | 141 +++++++++++++++++++++++- src/system/kernel/arch/x86/64/stubs.cpp | 23 ---- 2 files changed, 140 insertions(+), 24 deletions(-) diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 4fe65734c1..58b4bcb994 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -1,6 +1,12 @@ /* * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. + * + * Copyright 2001, Travis Geiselbrecht. All rights reserved. + * Copyright 2002, Michael Noisternig. All rights reserved. + * Distributed under the terms of the NewOS License. */ @@ -78,7 +84,7 @@ FUNCTION_END(x86_64_thread_entry) /* void x86_context_switch(struct arch_thread* oldState, - struct arch_thread* newState); */ + struct arch_thread* newState); */ FUNCTION(x86_context_switch): // Just need to save callee-save registers: RBP, RBX, R12-15. push %r15 @@ -121,3 +127,136 @@ FUNCTION(x86_reboot): done: jmp done FUNCTION_END(x86_reboot) + + +/* status_t arch_cpu_user_memcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_memcpy): + // faultHandler -> r8, size -> rcx. + movq %rcx, %r8 + movq %rdx, %rcx + + // Set the fault handler, preserve old in rax. + movq (%r8), %rax + movq $.L_user_memcpy_error, (%r8) + + // Move by quadwords. + cld + movq %rcx, %r9 + shrq $3, %rcx + rep + movsq + + // Move any remaining data by bytes. + movq %r9, %rcx + andq $7, %rcx + rep + movsb + + // Restore the old fault handler and return. + movq %rax, (%r8) + xorl %eax, %eax + ret + +.L_user_memcpy_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rax, (%r8) + movl $-1, %eax + ret +FUNCTION_END(arch_cpu_user_memcpy) + + +/* status_t arch_cpu_user_memset(void* to, char c, size_t count, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_memset): + // c -> al, faultHandler -> r8, size -> rcx. + movw %si, %ax + movq %rcx, %r8 + movq %rdx, %rcx + + // Set the fault handler, preserve old in rdx. + movq (%r8), %rdx + movq $.L_user_memset_error, (%r8) + + rep + stosb + + // Restore the old fault handler and return. + movq %rdx, (%r8) + xorl %eax, %eax + ret + +.L_user_memset_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rdx, (%r8) + movl $-1, %eax + ret +FUNCTION_END(arch_cpu_user_memset) + + +/* ssize_t arch_cpu_user_strlcpy(void* to, const void* from, size_t size, + addr_t* faultHandler) */ +FUNCTION(arch_cpu_user_strlcpy): + // faultHandler -> r8, size -> rcx, source -> r9 (original value needed to + // calculate return value). + movq %rcx, %r8 + movq %rdx, %rcx + movq %rsi, %r9 + + // Set the fault handler, preserve old in rax. + movq (%r8), %rax + movq $.L_user_strlcpy_error, (%r8) + + // Check for 0 length. + cmp $0, %rcx + je .L_user_strlcpy_source_count + + // Copy at most count - 1 bytes. + dec %rcx + + // If count is now 0, skip straight to null terminating as our loop will + // otherwise overflow. + jnz .L_user_strlcpy_copy_begin + movb $0, (%rdi) + jmp .L_user_strlcpy_source_count + +.L_user_strlcpy_copy_begin: + cld +.L_user_strlcpy_copy_loop: + // Move data by bytes. + lodsb + stosb + test %al, %al + jz .L_user_strlcpy_source_done + loop .L_user_strlcpy_copy_loop + + // Null terminate string. + movb $0, (%rdi) + dec %rsi + +.L_user_strlcpy_source_count: + // Count remaining bytes in src + not %rcx + xor %al, %al + repnz + scasb + +.L_user_strlcpy_source_done: + // Restore the old fault handler + movq %rax, (%r8) + + // Calculate total string length and return. + movq %rsi, %rax + subq %r9, %rax + dec %rax + ret + +.L_user_strlcpy_error: + // Restore the old fault handler. Return a generic error, the wrapper + // routine will deal with it. + movq %rax, (%r8) + movq $-1, %rax + ret +FUNCTION_END(arch_cpu_user_strlcpy) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 2651c32a47..e4a02c973a 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -51,29 +51,6 @@ arch_commpage_init_post_cpus(void) } -ssize_t -arch_cpu_user_strlcpy(char* to, const char* from, size_t size, - addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memcpy(void* to, const void* from, size_t size, - addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memset(void* s, char c, size_t count, addr_t* faultHandler) -{ - return B_BAD_ADDRESS; -} - - void arch_debug_save_registers(struct arch_debug_registers* registers) { From 659bacac269ec0992603008ef436ee20505bd67f Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 11 Jul 2012 14:43:44 +0100 Subject: [PATCH 094/273] Compile arch_real_time_clock.cpp and arch_system_info.cpp for x86_64. --- .../system/arch/x86_64/arch_cpu_defs.h | 12 +++++ headers/private/system/syscalls.h | 2 +- src/system/kernel/arch/x86/64/stubs.cpp | 49 ------------------- src/system/kernel/arch/x86/Jamfile | 4 +- 4 files changed, 15 insertions(+), 52 deletions(-) create mode 100644 headers/private/system/arch/x86_64/arch_cpu_defs.h diff --git a/headers/private/system/arch/x86_64/arch_cpu_defs.h b/headers/private/system/arch/x86_64/arch_cpu_defs.h new file mode 100644 index 0000000000..e10ef985d4 --- /dev/null +++ b/headers/private/system/arch/x86_64/arch_cpu_defs.h @@ -0,0 +1,12 @@ +/* + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _SYSTEM_ARCH_X86_DEFS_H +#define _SYSTEM_ARCH_X86_DEFS_H + + +#define SPINLOCK_PAUSE() asm volatile("pause;") + + +#endif /* _SYSTEM_ARCH_X86_DEFS_H */ diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 81cd20c10e..17f9b73d79 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -534,7 +534,7 @@ extern void _kern_clear_caches(void *address, size_t length, extern bool _kern_cpu_enabled(int32 cpu); extern status_t _kern_set_cpu_enabled(int32 cpu, bool enabled); -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) // our only x86 only syscall extern status_t _kern_get_cpuid(cpuid_info *info, uint32 eax, uint32 cpu); #endif diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index e4a02c973a..813e00c77e 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -270,41 +270,6 @@ arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, } -status_t -arch_rtc_init(struct kernel_args *args, struct real_time_data *data) -{ - return B_OK; -} - - -uint32 -arch_rtc_get_hw_time(void) -{ - return 0; -} - - -void -arch_rtc_set_hw_time(uint32 seconds) -{ - -} - - -void -arch_rtc_set_system_time_offset(struct real_time_data *data, bigtime_t offset) -{ - -} - - -bigtime_t -arch_rtc_get_system_time_offset(struct real_time_data *data) -{ - return 0; -} - - status_t arch_smp_init(kernel_args *args) { @@ -333,20 +298,6 @@ arch_smp_send_ici(int32 target_cpu) } -status_t -arch_get_system_info(system_info *info, size_t size) -{ - return B_OK; -} - - -status_t -arch_system_info_init(struct kernel_args *args) -{ - return B_OK; -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 0fac1a03aa..014c7135eb 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -48,9 +48,7 @@ if $(TARGET_ARCH) = x86_64 { arch_commpage.cpp arch_debug.cpp - arch_real_time_clock.cpp arch_smp.cpp - arch_system_info.cpp arch_user_debugger.cpp apm.cpp bios.cpp @@ -84,6 +82,8 @@ local archGenericSources = arch_elf.cpp arch_int.cpp arch_platform.cpp + arch_real_time_clock.cpp + arch_system_info.cpp arch_thread.cpp arch_timer.cpp arch_vm.cpp From 76a1175dbe1a314563ca18c0b7fb82695a9730cd Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 11 Jul 2012 18:29:15 +0100 Subject: [PATCH 095/273] Support for SMP on x86_64. No major changes to the kernel: just compiled in arch_smp.cpp and fixed the IDT load in arch_cpu_init_percpu to use the correct limit for x86_64 (uses sizeof(interrupt_descriptor)). In the boot loader, changed smp_boot_other_cpus to construct a temporary GDT and get the page directory address from CR3, as what's in kernel_args will be 64-bit stuff and will not work to switch the CPUs into 32-bit mode in the trampoline code. Refactored 64-bit kernel entry code to not use the stack after disabling paging, as the secondary CPUs are given a 32-bit virtual stack address by the SMP trampoline code which will no longer work. --- .../private/kernel/arch/x86/32/descriptors.h | 4 + .../boot/platform/bios_ia32/interrupts.cpp | 5 - src/system/boot/platform/bios_ia32/long.cpp | 65 ++++++++--- src/system/boot/platform/bios_ia32/long.h | 4 - src/system/boot/platform/bios_ia32/long_asm.S | 53 +++++---- src/system/boot/platform/bios_ia32/smp.cpp | 108 +++++------------- src/system/boot/platform/bios_ia32/smp.h | 4 +- src/system/boot/platform/bios_ia32/start.cpp | 51 ++++++++- src/system/kernel/arch/x86/32/int.cpp | 11 +- src/system/kernel/arch/x86/64/stubs.cpp | 28 ----- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_cpu.cpp | 5 +- src/system/kernel/arch/x86/arch_smp.cpp | 9 +- 13 files changed, 177 insertions(+), 172 deletions(-) diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h index c578acfd16..81fd842e8d 100644 --- a/headers/private/kernel/arch/x86/32/descriptors.h +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -50,6 +50,10 @@ typedef struct segment_descriptor { uint32 base_31_24 : 8; // 24 - 31 } segment_descriptor; +typedef struct interrupt_descriptor { + uint32 a, b; +} interrupt_descriptor; + struct tss { uint16 prev_task; uint16 unused0; diff --git a/src/system/boot/platform/bios_ia32/interrupts.cpp b/src/system/boot/platform/bios_ia32/interrupts.cpp index c5efc58ad5..2d5d0fa596 100644 --- a/src/system/boot/platform/bios_ia32/interrupts.cpp +++ b/src/system/boot/platform/bios_ia32/interrupts.cpp @@ -83,11 +83,6 @@ struct interrupt_frame { uint32 eflags; }; -struct interrupt_descriptor { - uint32 a; - uint32 b; -}; - static interrupt_descriptor sDebugIDT[DEBUG_IDT_SLOT_COUNT]; diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 28137d48eb..3e50305afd 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -23,6 +23,7 @@ #include #include "debug.h" +#include "smp.h" #include "mmu.h" @@ -31,6 +32,13 @@ static const uint64 kLargePageMappingFlags = 0x183; static const uint64 kPageMappingFlags = 0x103; // Global, R/W, Present +extern "C" void long_enter_kernel(int currentCPU, uint64 stackTop); + +extern uint32 gLongPhysicalGDT; +extern uint64 gLongVirtualGDT; +extern uint32 gLongPhysicalPML4; +extern uint64 gLongKernelEntry; + /*! Convert a 32-bit address to a 64-bit address. */ static inline uint64 @@ -71,6 +79,10 @@ long_gdt_init() DPL_USER); set_segment_descriptor(&gdt[USER_DATA_SEG / 8], DT_DATA_WRITEABLE, DPL_USER); + + // Used by long_enter_kernel(). + gLongPhysicalGDT = gKernelArgs.arch_args.phys_gdt; + gLongVirtualGDT = gKernelArgs.arch_args.vir_gdt; } @@ -222,6 +234,8 @@ long_mmu_init() gKernelArgs.virtual_allocated_range[i].start, gKernelArgs.virtual_allocated_range[i].size); } + + gLongPhysicalPML4 = gKernelArgs.arch_args.phys_pgdir; } @@ -275,12 +289,6 @@ convert_kernel_args() gKernelArgs.kernel_args_range[i].size); } - // Set correct kernel stack addresses. - for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) { - gKernelArgs.cpu_kstack[i].start = fix_address( - gKernelArgs.cpu_kstack[i].start); - } - // Fix driver settings files. driver_settings_file* file = gKernelArgs.driver_settings; fix_address(gKernelArgs.driver_settings); @@ -293,6 +301,27 @@ convert_kernel_args() } +static void +long_smp_start_kernel(void) +{ + uint32 cpu = smp_get_current_cpu(); + + // Important. Make sure supervisor threads can fault on read only pages... + asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); + asm("cld"); + asm("fninit"); + + // Fix our kernel stack address. + gKernelArgs.cpu_kstack[cpu].start + = fix_address(gKernelArgs.cpu_kstack[cpu].start); + + long_enter_kernel(cpu, gKernelArgs.cpu_kstack[cpu].start + + gKernelArgs.cpu_kstack[cpu].size); + + panic("Shouldn't get here"); +} + + void long_start_kernel() { @@ -305,8 +334,7 @@ long_start_kernel() preloaded_elf64_image *image = static_cast( gKernelArgs.kernel_image.Pointer()); - // TODO: x86_64 SMP, disable for now. - gKernelArgs.num_cpus = 1; + smp_init_other_cpus(); long_gdt_init(); long_idt_init(); @@ -315,23 +343,22 @@ long_start_kernel() debug_cleanup(); - // Calculate the arguments for long_enter_kernel(). - uint64 entry = image->elf_header.e_entry; - uint64 stackTop = gKernelArgs.cpu_kstack[0].start - + gKernelArgs.cpu_kstack[0].size; - uint64 kernelArgs = (addr_t)&gKernelArgs; + // Save the kernel entry point address. + gLongKernelEntry = image->elf_header.e_entry; + dprintf("kernel entry at %#llx\n", gLongKernelEntry); - dprintf("kernel entry at %#llx, stack %#llx, args %#llx\n", entry, - stackTop, kernelArgs); + // Fix our kernel stack address. + gKernelArgs.cpu_kstack[0].start + = fix_address(gKernelArgs.cpu_kstack[0].start); // We're about to enter the kernel -- disable console output. stdout = NULL; + smp_boot_other_cpus(long_smp_start_kernel); + // Enter the kernel! - long_enter_kernel(gKernelArgs.arch_args.phys_pgdir, - gKernelArgs.arch_args.phys_gdt, gKernelArgs.arch_args.vir_gdt, - entry, stackTop, kernelArgs, 0); + long_enter_kernel(0, gKernelArgs.cpu_kstack[0].start + + gKernelArgs.cpu_kstack[0].size); panic("Shouldn't get here"); } - diff --git a/src/system/boot/platform/bios_ia32/long.h b/src/system/boot/platform/bios_ia32/long.h index 084b5b36e8..e29d2aa66f 100644 --- a/src/system/boot/platform/bios_ia32/long.h +++ b/src/system/boot/platform/bios_ia32/long.h @@ -9,10 +9,6 @@ #include -extern "C" void long_enter_kernel(uint32 physPML4, uint32 physGDT, - uint64 virtGDT, uint64 entry, uint64 stackTop, uint64 kernelArgs, - int currentCPU); - extern void long_start_kernel(); diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 30bfd2be02..8c07f391ec 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -17,15 +17,17 @@ .code32 -/*! void long_enter_kernel(uint32 physPML4, uint32 physGDT, uint64 virtGDT, - uint64 entry, uint64 stackTop, uint64 kernelArgs, int currentCPU); -*/ +/*! void long_enter_kernel(int currentCPU, uint64 stackTop); */ FUNCTION(long_enter_kernel): + // Preserve the arguments. We may no longer be able to use the stack once + // paging is disabled. + movl 4(%esp), %ebx + movl 8(%esp), %edi + movl 12(%esp), %esi + // We're about to disable paging, so we need to load the the physical // address of our GDT. - movl 8(%esp), %eax - movl %eax, (long_gdtr + 2) - lgdtl (long_gdtr) + lgdtl long_phys_gdtr // Currently running with 32-bit paging tables at an identity mapped // address. To switch to 64-bit paging we must first disable 32-bit paging, @@ -40,11 +42,11 @@ FUNCTION(long_enter_kernel): movl %eax, %cr4 // Point CR3 to the kernel's PML4. - movl 4(%esp), %eax + movl gLongPhysicalPML4, %eax movl %eax, %cr3 // Enable long mode by setting EFER.LME. - movl $0xC0000080, %ecx + movl $0xc0000080, %ecx rdmsr orl $(1 << 8), %eax wrmsr @@ -68,32 +70,41 @@ FUNCTION(long_enter_kernel): mov %ax, %fs mov %ax, %gs - // Clear the high 32 bits of RSP. - movl %esp, %esp - // Load the virtual address of the GDT. - movq 12(%rsp), %rax - movq %rax, long_gdtr + 2(%rip) - lgdtq long_gdtr(%rip) + lgdtq long_virt_gdtr(%rip) - // Get the entry point address, arguments and new stack pointer. - movq 20(%rsp), %rax - movq 36(%rsp), %rdi - movl 44(%rsp), %esi - movq 28(%rsp), %rsp + // Set the stack pointer. + movl %edi, %esp + shl $32, %rsi + orq %rsi, %rsp // Clear the stack frame/RFLAGS. xorq %rbp, %rbp push $0 popf - // Call the kernel entry point. + // Get arguments and call the kernel entry point. + leaq gKernelArgs(%rip), %rdi + movl %ebx, %esi + movq gLongKernelEntry(%rip), %rax call *%rax .data -long_gdtr: +long_phys_gdtr: .word GDT_LIMIT - 1 +SYMBOL(gLongPhysicalGDT): + .long 0 + +long_virt_gdtr: + .word GDT_LIMIT - 1 +SYMBOL(gLongVirtualGDT): + .quad 0 + +SYMBOL(gLongPhysicalPML4): + .long 0 + +SYMBOL(gLongKernelEntry): .quad 0 diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index a7ec21b11a..0c6c5f7720 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -20,8 +20,10 @@ #include #include #include +#include #include #include +#include #include "mmu.h" #include "acpi.h" @@ -37,10 +39,6 @@ # define TRACE(x) ; #endif -struct gdt_idt_descr { - uint16 a; - uint32 *b; -} _PACKED; static struct scan_spots_struct smp_scan_spots[] = { { 0x9fc00, 0xa0000, 0xa0000 - 0x9fc00 }, @@ -54,9 +52,6 @@ extern "C" void smp_trampoline(void); extern "C" void smp_trampoline_end(void); -static int smp_get_current_cpu(void); - - static uint32 apic_read(uint32 offset) { @@ -71,22 +66,6 @@ apic_write(uint32 offset, uint32 data) } -static int -smp_get_current_cpu(void) -{ - if (gKernelArgs.arch_args.apic == NULL) - return 0; - - uint8 apicID = apic_read(APIC_ID) >> 24; - for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) { - if (gKernelArgs.arch_args.cpu_apic_id[i] == apicID) - return i; - } - - return 0; -} - - static mp_floating_struct * smp_mp_probe(uint32 base, uint32 limit) { @@ -341,56 +320,6 @@ smp_do_acpi_config(void) } -/*! Target function of the trampoline code. - The trampoline code should have the pgdir and a gdt set up for us, - along with us being on the final stack for this processor. We need - to set up the local APIC and load the global idt and gdt. When we're - done, we'll jump into the kernel with the cpu number as an argument. -*/ -static int -smp_cpu_ready(void) -{ - uint32 curr_cpu = smp_get_current_cpu(); - struct gdt_idt_descr idt_descr; - struct gdt_idt_descr gdt_descr; - - //TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu)); - - preloaded_elf32_image *image = static_cast( - gKernelArgs.kernel_image.Pointer()); - - // Important. Make sure supervisor threads can fault on read only pages... - asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); - asm("cld"); - asm("fninit"); - - // Set up the final idt - idt_descr.a = IDT_LIMIT - 1; - idt_descr.b = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt; - - asm("lidt %0;" - : : "m" (idt_descr)); - - // Set up the final gdt - gdt_descr.a = GDT_LIMIT - 1; - gdt_descr.b = (uint32 *)gKernelArgs.arch_args.vir_gdt; - - asm("lgdt %0;" - : : "m" (gdt_descr)); - - asm("pushl %0; " // push the cpu number - "pushl %1; " // kernel args - "pushl $0x0;" // dummy retval for call to main - "pushl %2; " // this is the start address - "ret; " // jump. - : : "g" (curr_cpu), "g" (&gKernelArgs), - "g" (image->elf_header.e_entry)); - - // no where to return to - return 0; -} - - static void calculate_apic_timer_conversion_factor(void) { @@ -429,6 +358,22 @@ calculate_apic_timer_conversion_factor(void) // #pragma mark - +int +smp_get_current_cpu(void) +{ + if (gKernelArgs.arch_args.apic == NULL) + return 0; + + uint8 apicID = apic_read(APIC_ID) >> 24; + for (uint32 i = 0; i < gKernelArgs.num_cpus; i++) { + if (gKernelArgs.arch_args.cpu_apic_id[i] == apicID) + return i; + } + + return 0; +} + + void smp_init_other_cpus(void) { @@ -476,7 +421,7 @@ smp_init_other_cpus(void) void -smp_boot_other_cpus(void) +smp_boot_other_cpus(void (*entryFunc)()) { if (gKernelArgs.num_cpus < 2) return; @@ -516,7 +461,7 @@ smp_boot_other_cpus(void) tempStack = (finalStack + (KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE) / sizeof(uint32)) - 1; - *tempStack = (uint32)&smp_cpu_ready; + *tempStack = (uint32)entryFunc; // set the trampoline stack up tempStack = (uint32 *)(trampolineStack + B_PAGE_SIZE - 4); @@ -525,15 +470,20 @@ smp_boot_other_cpus(void) + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE - sizeof(uint32); tempStack--; // page dir - *tempStack = gKernelArgs.arch_args.phys_pgdir; + *tempStack = x86_read_cr3() & 0xfffff000; // put a gdt descriptor at the bottom of the stack *((uint16 *)trampolineStack) = 0x18 - 1; // LIMIT *((uint32 *)(trampolineStack + 2)) = trampolineStack + 8; - // put the gdt at the bottom - memcpy(&((uint32 *)trampolineStack)[2], - (void *)gKernelArgs.arch_args.vir_gdt, 6 * 4); + // construct a temporary gdt at the bottom + segment_descriptor* tempGDT + = (segment_descriptor*)&((uint32 *)trampolineStack)[2]; + clear_segment_descriptor(&tempGDT[0]); + set_segment_descriptor(&tempGDT[1], 0, 0xffffffff, DT_CODE_READABLE, + DPL_KERNEL); + set_segment_descriptor(&tempGDT[2], 0, 0xffffffff, DT_DATA_WRITEABLE, + DPL_KERNEL); /* clear apic errors */ if (gKernelArgs.arch_args.cpu_apic_version[i] & 0xf0) { diff --git a/src/system/boot/platform/bios_ia32/smp.h b/src/system/boot/platform/bios_ia32/smp.h index bf942a0925..2380e63072 100644 --- a/src/system/boot/platform/bios_ia32/smp.h +++ b/src/system/boot/platform/bios_ia32/smp.h @@ -19,7 +19,9 @@ extern "C" { extern void smp_init(void); extern void smp_init_other_cpus(void); -extern void smp_boot_other_cpus(void); +extern void smp_boot_other_cpus(void (*entryFunc)()); + +extern int smp_get_current_cpu(void); #ifdef __cplusplus } diff --git a/src/system/boot/platform/bios_ia32/start.cpp b/src/system/boot/platform/bios_ia32/start.cpp index 717b2c203b..2cc72123fb 100644 --- a/src/system/boot/platform/bios_ia32/start.cpp +++ b/src/system/boot/platform/bios_ia32/start.cpp @@ -73,6 +73,55 @@ platform_boot_options(void) } +/*! Target function of the SMP trampoline code. + The trampoline code should have the pgdir and a gdt set up for us, + along with us being on the final stack for this processor. We need + to set up the local APIC and load the global idt and gdt. When we're + done, we'll jump into the kernel with the cpu number as an argument. +*/ +static void +smp_start_kernel(void) +{ + uint32 curr_cpu = smp_get_current_cpu(); + struct gdt_idt_descr idt_descr; + struct gdt_idt_descr gdt_descr; + + //TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu)); + + preloaded_elf32_image *image = static_cast( + gKernelArgs.kernel_image.Pointer()); + + // Important. Make sure supervisor threads can fault on read only pages... + asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1)); + asm("cld"); + asm("fninit"); + + // Set up the final idt + idt_descr.limit = IDT_LIMIT - 1; + idt_descr.base = (uint32 *)(addr_t)gKernelArgs.arch_args.vir_idt; + + asm("lidt %0;" + : : "m" (idt_descr)); + + // Set up the final gdt + gdt_descr.limit = GDT_LIMIT - 1; + gdt_descr.base = (uint32 *)gKernelArgs.arch_args.vir_gdt; + + asm("lgdt %0;" + : : "m" (gdt_descr)); + + asm("pushl %0; " // push the cpu number + "pushl %1; " // kernel args + "pushl $0x0;" // dummy retval for call to main + "pushl %2; " // this is the start address + "ret; " // jump. + : : "g" (curr_cpu), "g" (&gKernelArgs), + "g" (image->elf_header.e_entry)); + + panic("kernel returned!\n"); +} + + extern "C" void platform_start_kernel(void) { @@ -99,7 +148,7 @@ platform_start_kernel(void) // We're about to enter the kernel -- disable console output. stdout = NULL; - smp_boot_other_cpus(); + smp_boot_other_cpus(smp_start_kernel); dprintf("kernel entry at %lx\n", image->elf_header.e_entry); diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index c49ec88d0a..b290c0df46 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -62,10 +62,7 @@ static const int kInterruptNameCount = 20; #define MAX_ARGS 16 -typedef struct { - uint32 a, b; -} desc_table; -static desc_table* sIDTs[B_MAX_CPU_COUNT]; +static interrupt_descriptor* sIDTs[B_MAX_CPU_COUNT]; // table with functions handling respective interrupts typedef void interrupt_handler_function(struct iframe* frame); @@ -80,7 +77,7 @@ extern void hardware_interrupt(struct iframe* frame); /*! Initializes a descriptor in an IDT. */ static void -set_gate(desc_table *gate_addr, addr_t addr, int type, int dpl) +set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl) { unsigned int gate1; // first byte of gate desc unsigned int gate2; // second byte of gate desc @@ -353,7 +350,7 @@ arch_int_init(struct kernel_args *args) interrupt_handler_function** table; // set the global sIDT variable - sIDTs[0] = (desc_table *)(addr_t)args->arch_args.vir_idt; + sIDTs[0] = (interrupt_descriptor *)(addr_t)args->arch_args.vir_idt; // setup the standard programmable interrupt controller pic_init(); @@ -668,7 +665,7 @@ arch_int_init_post_vm(struct kernel_args *args) int32 cpuCount = smp_get_num_cpus(); if (cpuCount > 0) { size_t areaSize = ROUNDUP(cpuCount * idtSize, B_PAGE_SIZE); - desc_table* idt; + interrupt_descriptor* idt; virtual_address_restrictions virtualRestrictions = {}; virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; physical_address_restrictions physicalRestrictions = {}; diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 813e00c77e..72b95c6449 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -270,34 +270,6 @@ arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, } -status_t -arch_smp_init(kernel_args *args) -{ - return B_OK; -} - - -status_t -arch_smp_per_cpu_init(kernel_args *args, int32 cpu) -{ - return B_OK; -} - - -void -arch_smp_send_broadcast_ici(void) -{ - -} - - -void -arch_smp_send_ici(int32 target_cpu) -{ - -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 014c7135eb..4d4329bd98 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -48,7 +48,6 @@ if $(TARGET_ARCH) = x86_64 { arch_commpage.cpp arch_debug.cpp - arch_smp.cpp arch_user_debugger.cpp apm.cpp bios.cpp @@ -83,6 +82,7 @@ local archGenericSources = arch_int.cpp arch_platform.cpp arch_real_time_clock.cpp + arch_smp.cpp arch_system_info.cpp arch_thread.cpp arch_timer.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 9fe0d79075..12b8f2848f 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -349,7 +349,7 @@ x86_init_fpu(void) static void load_tss(int cpu) { - short seg = ((TSS_BASE_SEGMENT + cpu) << 3) | DPL_KERNEL; + short seg = (TSS_SEGMENT(cpu) << 3) | DPL_KERNEL; asm("ltr %%ax" : : "a" (seg)); } @@ -789,7 +789,8 @@ arch_cpu_init_percpu(kernel_args* args, int cpu) uint16 limit; void* address; } _PACKED descriptor = { - 256 * 8 - 1, // 256 descriptors, 8 bytes each (-1 for "limit") + 256 * sizeof(interrupt_descriptor) - 1, + // 256 descriptors (-1 for "limit") x86_get_idt(cpu) }; diff --git a/src/system/kernel/arch/x86/arch_smp.cpp b/src/system/kernel/arch/x86/arch_smp.cpp index a63051be29..b1aedd89f0 100644 --- a/src/system/kernel/arch/x86/arch_smp.cpp +++ b/src/system/kernel/arch/x86/arch_smp.cpp @@ -52,7 +52,7 @@ static int32 x86_spurious_interrupt(void *data) { // spurious interrupt - TRACE(("spurious interrupt on cpu %ld\n", smp_get_current_cpu())); + TRACE(("spurious interrupt on cpu %" B_PRId32 "\n", smp_get_current_cpu())); // spurious interrupts must not be acknowledged as it does not expect // a end of interrupt - if we still do it we would loose the next best @@ -65,7 +65,7 @@ static int32 x86_smp_error_interrupt(void *data) { // smp error interrupt - TRACE(("smp error interrupt on cpu %ld\n", smp_get_current_cpu())); + TRACE(("smp error interrupt on cpu %" B_PRId32 "\n", smp_get_current_cpu())); return B_HANDLED_INTERRUPT; } @@ -104,7 +104,8 @@ status_t arch_smp_per_cpu_init(kernel_args *args, int32 cpu) { // set up the local apic on the current cpu - TRACE(("arch_smp_init_percpu: setting up the apic on cpu %ld\n", cpu)); + TRACE(("arch_smp_init_percpu: setting up the apic on cpu %" B_PRId32 "\n", + cpu)); apic_per_cpu_init(args, cpu); // setup FPU and SSE if supported @@ -154,7 +155,7 @@ arch_smp_send_ici(int32 target_cpu) asm volatile ("pause;"); if (timeout == 0) - panic("arch_smp_send_ici: timeout, target_cpu %ld", target_cpu); + panic("arch_smp_send_ici: timeout, target_cpu %" B_PRId32, target_cpu); restore_interrupts(state); } From c3f0fd28cda13d70a8c092003609442e4e29cf78 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 11:29:33 +0100 Subject: [PATCH 096/273] Fixed formatting of output in some debugger commands. Currently all debugger commands assume 32-bit pointers when formatting their output. This means that on x86_64 the output is incorrectly formatted. Fixed this by adding a B_PRINTF_POINTER_WIDTH definition (16 on 64-bit, 8 on 32-bit), and using this to correctly format the output. Not all commands have been fixed yet, but all VM, slab, VFS, team, thread and image commands should be correct. --- headers/os/support/SupportDefs.h | 8 +++++++ src/system/kernel/elf.cpp | 6 ++--- src/system/kernel/fs/vfs.cpp | 19 +++++++++------ src/system/kernel/image.cpp | 3 ++- src/system/kernel/sem.cpp | 3 ++- src/system/kernel/slab/MemoryManager.cpp | 10 ++++---- src/system/kernel/slab/Slab.cpp | 8 ++++--- src/system/kernel/team.cpp | 3 ++- src/system/kernel/thread.cpp | 30 ++++++++++++++---------- src/system/kernel/vm/VMAddressSpace.cpp | 5 ++-- src/system/kernel/vm/vm.cpp | 6 +++-- 11 files changed, 64 insertions(+), 37 deletions(-) diff --git a/headers/os/support/SupportDefs.h b/headers/os/support/SupportDefs.h index 0529525366..e4f0c24e53 100644 --- a/headers/os/support/SupportDefs.h +++ b/headers/os/support/SupportDefs.h @@ -148,6 +148,14 @@ typedef generic_addr_t generic_size_t; #define B_PRIiTIME B_PRIi32 +/* Printed width of a pointer with the %p format (minus 0x prefix). */ +#ifdef B_HAIKU_64_BIT +# define B_PRINTF_POINTER_WIDTH 16 +#else +# define B_PRINTF_POINTER_WIDTH 8 +#endif + + /* Empty string ("") */ #ifdef __cplusplus extern const char *B_EMPTY_STRING; diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 59e2928b2a..e4682fe561 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -463,8 +463,8 @@ dump_symbols(int argc, char **argv) // dump symbols - kprintf("Symbols of image %" B_PRId32 "\"%s\":\n" - "Address Type Size Name\n", image->id, image->name); + kprintf("Symbols of image %" B_PRId32 "\"%s\":\n", image->id, image->name); + kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address"); if (image->num_debug_symbols > 0) { // search extended debug symbol table (contains static symbols) @@ -475,7 +475,7 @@ dump_symbols(int argc, char **argv) >= image->text_region.size + image->data_region.size) continue; - kprintf("%08lx %s/%s %5ld %s\n", + kprintf("%0*lx %s/%s %5ld %s\n", B_PRINTF_POINTER_WIDTH, symbol->st_value + image->text_region.delta, get_symbol_type_string(symbol), get_symbol_bind_string(symbol), symbol->st_size, image->debug_string_table + symbol->st_name); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index d2a5e768f3..6e4dfd2d39 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -3174,7 +3174,9 @@ dump_mounts(int argc, char** argv) return 0; } - kprintf("address id root covers cookie fs_name\n"); + kprintf("%-*s id %-*s %-*s %-*s fs_name\n", + B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "root", + B_PRINTF_POINTER_WIDTH, "covers", B_PRINTF_POINTER_WIDTH, "cookie"); struct hash_iterator iterator; struct fs_mount* mount; @@ -3257,8 +3259,9 @@ dump_vnodes(int argc, char** argv) struct hash_iterator iterator; struct vnode* vnode; - kprintf("address dev inode ref cache fs-node locking " - "flags\n"); + kprintf("%-*s dev inode ref %-*s %-*s %-*s flags\n", + B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "cache", + B_PRINTF_POINTER_WIDTH, "fs-node", B_PRINTF_POINTER_WIDTH, "locking"); hash_open(sVnodeTable, &iterator); while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { @@ -3293,7 +3296,8 @@ dump_vnode_caches(int argc, char** argv) if (argc > 1) device = parse_expression(argv[1]); - kprintf("address dev inode cache size pages\n"); + kprintf("%-*s dev inode %-*s size pages\n", + B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "cache"); hash_open(sVnodeTable, &iterator); while ((vnode = (struct vnode*)hash_next(sVnodeTable, &iterator)) != NULL) { @@ -3344,9 +3348,10 @@ dump_io_context(int argc, char** argv) kprintf(" used fds:\t%" B_PRIu32 "\n", context->num_used_fds); kprintf(" max fds:\t%" B_PRIu32 "\n", context->table_size); - if (context->num_used_fds) - kprintf(" no. type ops ref open mode pos" - " cookie\n"); + if (context->num_used_fds) { + kprintf(" no. type %*s ref open mode pos %*s\n", + B_PRINTF_POINTER_WIDTH, "ops", B_PRINTF_POINTER_WIDTH, "cookie"); + } for (uint32 i = 0; i < context->table_size; i++) { struct file_descriptor* fd = context->fds[i]; diff --git a/src/system/kernel/image.cpp b/src/system/kernel/image.cpp index 787124db81..1de30f7c0a 100644 --- a/src/system/kernel/image.cpp +++ b/src/system/kernel/image.cpp @@ -261,7 +261,8 @@ dump_images_list(int argc, char **argv) team = thread_get_current_thread()->team; kprintf("Registered images of team %" B_PRId32 "\n", team->id); - kprintf(" ID text size data size name\n"); + kprintf(" ID %-*s size %-*s size name\n", + B_PRINTF_POINTER_WIDTH, "text", B_PRINTF_POINTER_WIDTH, "data"); while ((image = (struct image*)list_get_next_item(&team->image_list, image)) != NULL) { diff --git a/src/system/kernel/sem.cpp b/src/system/kernel/sem.cpp index 5a5a20af43..747428e4c9 100644 --- a/src/system/kernel/sem.cpp +++ b/src/system/kernel/sem.cpp @@ -153,7 +153,8 @@ dump_sem_list(int argc, char** argv) } else if (argc > 1) owner = strtoul(argv[1], NULL, 0); - kprintf("sem id count team last name\n"); + kprintf("%-*s id count team last name\n", B_PRINTF_POINTER_WIDTH, + "sem"); for (i = 0; i < sMaxSems; i++) { struct sem_entry* sem = &sSems[i]; diff --git a/src/system/kernel/slab/MemoryManager.cpp b/src/system/kernel/slab/MemoryManager.cpp index f21d5ed392..4791d4b79c 100644 --- a/src/system/kernel/slab/MemoryManager.cpp +++ b/src/system/kernel/slab/MemoryManager.cpp @@ -1766,7 +1766,8 @@ MemoryManager::_CheckMetaChunk(MetaChunk* metaChunk) /*static*/ int MemoryManager::_DumpRawAllocations(int argc, char** argv) { - kprintf("area meta chunk chunk base size (KB)\n"); + kprintf("%-*s meta chunk chunk %-*s size (KB)\n", + B_PRINTF_POINTER_WIDTH, "area", B_PRINTF_POINTER_WIDTH, "base"); size_t totalSize = 0; @@ -1798,8 +1799,8 @@ MemoryManager::_DumpRawAllocations(int argc, char** argv) } } - kprintf("total: %9" B_PRIuSIZE "\n", - totalSize / 1024); + kprintf("total:%*s%9" B_PRIuSIZE "\n", (2 * B_PRINTF_POINTER_WIDTH) + 21, + "", totalSize / 1024); return 0; } @@ -1976,7 +1977,8 @@ MemoryManager::_DumpArea(int argc, char** argv) /*static*/ int MemoryManager::_DumpAreas(int argc, char** argv) { - kprintf(" base area meta small medium large\n"); + kprintf(" %*s %*s meta small medium large\n", + B_PRINTF_POINTER_WIDTH, "base", B_PRINTF_POINTER_WIDTH, "area"); size_t totalTotalSmall = 0; size_t totalUsedSmall = 0; diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index 327506ae73..81a8cdd0ad 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -258,8 +258,9 @@ dump_slab(::slab* slab) static int dump_slabs(int argc, char* argv[]) { - kprintf("%10s %22s %8s %8s %8s %6s %8s %8s %8s\n", "address", "name", - "objsize", "align", "usage", "empty", "usedobj", "total", "flags"); + kprintf("%*s %22s %8s %8s %8s %6s %8s %8s %8s\n", + B_PRINTF_POINTER_WIDTH + 2, "address", "name", "objsize", "align", + "usage", "empty", "usedobj", "total", "flags"); ObjectCacheList::Iterator it = sObjectCaches.GetIterator(); @@ -303,7 +304,8 @@ dump_cache_info(int argc, char* argv[]) kprintf("resize entry don't wait: %p\n", cache->resize_entry_dont_wait); kprintf("resize entry can wait: %p\n", cache->resize_entry_can_wait); - kprintf(" slab chunk size used offset free\n"); + kprintf(" %-*s %-*s size used offset free\n", + B_PRINTF_POINTER_WIDTH, "slab", B_PRINTF_POINTER_WIDTH, "chunk"); SlabList::Iterator iterator = cache->empty.GetIterator(); if (iterator.HasNext()) diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index c8ac2cfd5e..0373b55c43 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1185,7 +1185,8 @@ dump_team_info(int argc, char** argv) static int dump_teams(int argc, char** argv) { - kprintf("team id parent name\n"); + kprintf("%-*s id %-*s name\n", B_PRINTF_POINTER_WIDTH, "team", + B_PRINTF_POINTER_WIDTH, "parent"); for (TeamTable::Iterator it = sTeamHash.GetIterator(); Team* team = it.Next();) { diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index f392756e8c..76cb73c156 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -1595,8 +1595,10 @@ state_to_text(Thread *thread, int32 state) static void print_thread_list_table_head() { - kprintf("thread id state wait for object cpu pri stack " - " team name\n"); + kprintf("%-*s id state wait for %-*s cpu pri %-*s team " + "name\n", + B_PRINTF_POINTER_WIDTH, "thread", B_PRINTF_POINTER_WIDTH, "object", + B_PRINTF_POINTER_WIDTH, "stack"); } @@ -1614,42 +1616,44 @@ _dump_thread_info(Thread *thread, bool shortInfo) { sem_id sem = (sem_id)(addr_t)thread->wait.object; if (sem == thread->msg.read_sem) - kprintf(" "); - else - kprintf("sem %12" B_PRId32 " ", sem); + kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); + else { + kprintf("sem %-*" B_PRId32, + B_PRINTF_POINTER_WIDTH + 5, sem); + } break; } case THREAD_BLOCK_TYPE_CONDITION_VARIABLE: - kprintf("cvar %p ", thread->wait.object); + kprintf("cvar %p ", thread->wait.object); break; case THREAD_BLOCK_TYPE_SNOOZE: - kprintf(" "); + kprintf("%*s", B_PRINTF_POINTER_WIDTH + 15, ""); break; case THREAD_BLOCK_TYPE_SIGNAL: - kprintf("signal "); + kprintf("signal%*s", B_PRINTF_POINTER_WIDTH + 9, ""); break; case THREAD_BLOCK_TYPE_MUTEX: - kprintf("mutex %p ", thread->wait.object); + kprintf("mutex %p ", thread->wait.object); break; case THREAD_BLOCK_TYPE_RW_LOCK: - kprintf("rwlock %p ", thread->wait.object); + kprintf("rwlock %p ", thread->wait.object); break; case THREAD_BLOCK_TYPE_OTHER: - kprintf("other "); + kprintf("other%*s", B_PRINTF_POINTER_WIDTH + 10, ""); break; default: - kprintf("??? %p ", thread->wait.object); + kprintf("??? %p ", thread->wait.object); break; } } else - kprintf(" - "); + kprintf("-%*s", B_PRINTF_POINTER_WIDTH + 14, ""); // on which CPU does it run? if (thread->cpu) diff --git a/src/system/kernel/vm/VMAddressSpace.cpp b/src/system/kernel/vm/VMAddressSpace.cpp index c42e692473..46f3e12e1a 100644 --- a/src/system/kernel/vm/VMAddressSpace.cpp +++ b/src/system/kernel/vm/VMAddressSpace.cpp @@ -344,8 +344,9 @@ VMAddressSpace::_DumpCommand(int argc, char** argv) /*static*/ int VMAddressSpace::_DumpListCommand(int argc, char** argv) { - kprintf(" address id base end area count " - " area size\n"); + kprintf(" %*s id %*s %*s area count area size\n", + B_PRINTF_POINTER_WIDTH, "address", B_PRINTF_POINTER_WIDTH, "base", + B_PRINTF_POINTER_WIDTH, "end"); AddressSpaceTable::Iterator it = sAddressSpaceTable.GetIterator(); while (VMAddressSpace* space = it.Next()) { diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index b4f00fbbe3..5d5f936459 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -3372,7 +3372,9 @@ dump_area_list(int argc, char** argv) name = argv[1]; } - kprintf("addr id base\t\tsize protect lock name\n"); + kprintf("%-*s id %-*s %-*sprotect lock name\n", + B_PRINTF_POINTER_WIDTH, "addr", B_PRINTF_POINTER_WIDTH, "base", + B_PRINTF_POINTER_WIDTH, "size"); VMAreaHashTable::Iterator it = VMAreaHash::GetIterator(); while ((area = it.Next()) != NULL) { @@ -3380,7 +3382,7 @@ dump_area_list(int argc, char** argv) || (name != NULL && strstr(area->name, name) == NULL)) continue; - kprintf("%p %5" B_PRIx32 " %p\t%p %4" B_PRIx32 "\t%4d %s\n", area, + kprintf("%p %5" B_PRIx32 " %p %p %4" B_PRIx32 " %4d %s\n", area, area->id, (void*)area->Base(), (void*)area->Size(), area->protection, area->wiring, area->name); } From 6ba74ba51c14e84609239758cb01f674ffa335e8 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 12:21:09 +0100 Subject: [PATCH 097/273] Fixed compilation of the boot loader on GCC 2. Not sure why but GCC 2 seems to be ignoring the extern "C" in smp.h when compiling smp_boot_other_cpus() resulting in undefined references. Fixed by putting extern "C" on the definition too. --- src/system/boot/platform/bios_ia32/smp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 0c6c5f7720..ef9545344c 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -420,7 +420,7 @@ smp_init_other_cpus(void) } -void +extern "C" void smp_boot_other_cpus(void (*entryFunc)()) { if (gKernelArgs.num_cpus < 2) From 5774b5afa4f73fb010a7b7af03a9aa5f6deaec93 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 12:22:48 +0100 Subject: [PATCH 098/273] C++ified remaining C users of arch_cpu.h. --- src/add-ons/kernel/bus_managers/isa/Jamfile | 2 +- .../kernel/bus_managers/isa/arch/x86/Jamfile | 4 +-- .../{isa_controller.c => isa_controller.cpp} | 0 .../isa/arch/x86/{isa_dma.c => isa_dma.cpp} | 0 .../bus_managers/isa/{isa.c => isa.cpp} | 0 .../kernel/bus_managers/pci/arch/x86/Jamfile | 8 ++--- .../pci/arch/x86/{pci_bios.c => pci_bios.cpp} | 0 .../{pci_controller.c => pci_controller.cpp} | 30 +++++++++---------- .../pci/arch/x86/{pci_io.c => pci_io.cpp} | 0 .../pci/arch/x86/{pci_irq.c => pci_irq.cpp} | 0 src/libs/compat/freebsd_network/Jamfile | 2 +- .../compat/freebsd_network/{bus.c => bus.cpp} | 18 +++++++---- src/system/libroot/os/arch/x86/Jamfile | 2 +- .../libroot/os/arch/x86/{time.c => time.cpp} | 0 14 files changed, 36 insertions(+), 30 deletions(-) rename src/add-ons/kernel/bus_managers/isa/arch/x86/{isa_controller.c => isa_controller.cpp} (100%) rename src/add-ons/kernel/bus_managers/isa/arch/x86/{isa_dma.c => isa_dma.cpp} (100%) rename src/add-ons/kernel/bus_managers/isa/{isa.c => isa.cpp} (100%) rename src/add-ons/kernel/bus_managers/pci/arch/x86/{pci_bios.c => pci_bios.cpp} (100%) rename src/add-ons/kernel/bus_managers/pci/arch/x86/{pci_controller.c => pci_controller.cpp} (89%) rename src/add-ons/kernel/bus_managers/pci/arch/x86/{pci_io.c => pci_io.cpp} (100%) rename src/add-ons/kernel/bus_managers/pci/arch/x86/{pci_irq.c => pci_irq.cpp} (100%) rename src/libs/compat/freebsd_network/{bus.c => bus.cpp} (97%) rename src/system/libroot/os/arch/x86/{time.c => time.cpp} (100%) diff --git a/src/add-ons/kernel/bus_managers/isa/Jamfile b/src/add-ons/kernel/bus_managers/isa/Jamfile index d31c44db12..84a540a125 100644 --- a/src/add-ons/kernel/bus_managers/isa/Jamfile +++ b/src/add-ons/kernel/bus_managers/isa/Jamfile @@ -3,7 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers isa ; UsePrivateKernelHeaders ; KernelAddon isa : - isa.c + isa.cpp : isa_arch_bus_manager.a ; diff --git a/src/add-ons/kernel/bus_managers/isa/arch/x86/Jamfile b/src/add-ons/kernel/bus_managers/isa/arch/x86/Jamfile index 8c49de72a8..2618a2e39b 100644 --- a/src/add-ons/kernel/bus_managers/isa/arch/x86/Jamfile +++ b/src/add-ons/kernel/bus_managers/isa/arch/x86/Jamfile @@ -6,7 +6,7 @@ UsePrivateHeaders kernel [ FDirName kernel arch x86 ] ; UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ; KernelStaticLibrary isa_arch_bus_manager : - isa_dma.c - isa_controller.c + isa_dma.cpp + isa_controller.cpp ; diff --git a/src/add-ons/kernel/bus_managers/isa/arch/x86/isa_controller.c b/src/add-ons/kernel/bus_managers/isa/arch/x86/isa_controller.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/isa/arch/x86/isa_controller.c rename to src/add-ons/kernel/bus_managers/isa/arch/x86/isa_controller.cpp diff --git a/src/add-ons/kernel/bus_managers/isa/arch/x86/isa_dma.c b/src/add-ons/kernel/bus_managers/isa/arch/x86/isa_dma.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/isa/arch/x86/isa_dma.c rename to src/add-ons/kernel/bus_managers/isa/arch/x86/isa_dma.cpp diff --git a/src/add-ons/kernel/bus_managers/isa/isa.c b/src/add-ons/kernel/bus_managers/isa/isa.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/isa/isa.c rename to src/add-ons/kernel/bus_managers/isa/isa.cpp diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/Jamfile b/src/add-ons/kernel/bus_managers/pci/arch/x86/Jamfile index 9328c66541..f03f6c7048 100644 --- a/src/add-ons/kernel/bus_managers/pci/arch/x86/Jamfile +++ b/src/add-ons/kernel/bus_managers/pci/arch/x86/Jamfile @@ -7,9 +7,9 @@ UsePrivateHeaders kernel [ FDirName kernel arch x86 ] [ FDirName kernel util ] ; KernelStaticLibrary pci_arch_bus_manager : pci_arch_info.cpp pci_arch_module.cpp - pci_bios.c - pci_controller.c - pci_io.c - pci_irq.c + pci_bios.cpp + pci_controller.cpp + pci_io.cpp + pci_irq.cpp pci_msi.cpp ; diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_bios.c b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_bios.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/pci/arch/x86/pci_bios.c rename to src/add-ons/kernel/bus_managers/pci/arch/x86/pci_bios.cpp diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.c b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.cpp similarity index 89% rename from src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.c rename to src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.cpp index 79431d88c9..4a0fd7fc5a 100644 --- a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.c +++ b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_controller.cpp @@ -181,29 +181,29 @@ pci_ram_address(const void *physical_address_in_system_memory) pci_controller pci_controller_x86_mech1 = { - .read_pci_config = pci_mech1_read_config, - .write_pci_config = pci_mech1_write_config, - .get_max_bus_devices = pci_mech1_get_max_bus_devices, - .read_pci_irq = pci_x86_irq_read, - .write_pci_irq = pci_x86_irq_write, + pci_mech1_read_config, + pci_mech1_write_config, + pci_mech1_get_max_bus_devices, + pci_x86_irq_read, + pci_x86_irq_write, }; pci_controller pci_controller_x86_mech2 = { - .read_pci_config = pci_mech2_read_config, - .write_pci_config = pci_mech2_write_config, - .get_max_bus_devices = pci_mech2_get_max_bus_devices, - .read_pci_irq = pci_x86_irq_read, - .write_pci_irq = pci_x86_irq_write, + pci_mech2_read_config, + pci_mech2_write_config, + pci_mech2_get_max_bus_devices, + pci_x86_irq_read, + pci_x86_irq_write, }; pci_controller pci_controller_x86_bios = { - .read_pci_config = pci_bios_read_config, - .write_pci_config = pci_bios_write_config, - .get_max_bus_devices = pci_bios_get_max_bus_devices, - .read_pci_irq = pci_x86_irq_read, - .write_pci_irq = pci_x86_irq_write, + pci_bios_read_config, + pci_bios_write_config, + pci_bios_get_max_bus_devices, + pci_x86_irq_read, + pci_x86_irq_write, }; diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_io.c b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_io.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/pci/arch/x86/pci_io.c rename to src/add-ons/kernel/bus_managers/pci/arch/x86/pci_io.cpp diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_irq.c b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_irq.cpp similarity index 100% rename from src/add-ons/kernel/bus_managers/pci/arch/x86/pci_irq.c rename to src/add-ons/kernel/bus_managers/pci/arch/x86/pci_irq.cpp diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 28e747bd85..fff177a61b 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -13,7 +13,7 @@ Includes [ FGristFiles kernel_c++_structs.h ] SubDirCcFlags [ FDefines _KERNEL=1 ] ; KernelStaticLibrary libfreebsd_network.a : - bus.c + bus.cpp callout.cpp clock.c compat.c diff --git a/src/libs/compat/freebsd_network/bus.c b/src/libs/compat/freebsd_network/bus.cpp similarity index 97% rename from src/libs/compat/freebsd_network/bus.c rename to src/libs/compat/freebsd_network/bus.cpp index fddbd17637..edd40af9b8 100644 --- a/src/libs/compat/freebsd_network/bus.c +++ b/src/libs/compat/freebsd_network/bus.cpp @@ -5,12 +5,17 @@ */ +extern "C" { #include "device.h" +} #include +#include + #include +extern "C" { #include #include #include @@ -18,6 +23,7 @@ #include #include #include +} // private kernel header to get B_NO_HANDLED_INFO #include @@ -149,7 +155,7 @@ bus_alloc_resource(device_t dev, int type, int *rid, unsigned long start, "0x%lx)\n", type, *rid, start, end, count, flags); // maybe a local array of resources is enough - res = malloc(sizeof(struct resource)); + res = (struct resource *)malloc(sizeof(struct resource)); if (res == NULL) return NULL; @@ -256,7 +262,7 @@ rman_get_bustag(struct resource *res) static int32 intr_wrapper(void *data) { - struct internal_intr *intr = data; + struct internal_intr *intr = (struct internal_intr *)data; //device_printf(intr->dev, "in interrupt handler.\n"); @@ -271,7 +277,7 @@ intr_wrapper(void *data) static int32 intr_fast_wrapper(void *data) { - struct internal_intr *intr = data; + struct internal_intr *intr = (struct internal_intr *)data; intr->handler(intr->arg); @@ -283,7 +289,7 @@ intr_fast_wrapper(void *data) static int32 intr_handler(void *data) { - struct internal_intr *intr = data; + struct internal_intr *intr = (struct internal_intr *)data; status_t status; while (1) { @@ -398,7 +404,7 @@ bus_setup_intr(device_t dev, struct resource *res, int flags, int bus_teardown_intr(device_t dev, struct resource *res, void *arg) { - struct internal_intr *intr = arg; + struct internal_intr *intr = (struct internal_intr *)arg; if (intr->is_msi && gPCIx86 != NULL) { // disable msi generation @@ -892,7 +898,7 @@ pci_set_powerstate(device_t dev, int newPowerState) if (oldPowerState == newPowerState) return EOK; - switch (max(oldPowerState, newPowerState)) { + switch (std::max(oldPowerState, newPowerState)) { case PCI_POWERSTATE_D2: stateTransitionDelayInUs = 200; break; diff --git a/src/system/libroot/os/arch/x86/Jamfile b/src/system/libroot/os/arch/x86/Jamfile index 7806e44481..786a76eeda 100644 --- a/src/system/libroot/os/arch/x86/Jamfile +++ b/src/system/libroot/os/arch/x86/Jamfile @@ -19,7 +19,7 @@ MergeObject os_arch_$(TARGET_ARCH).o : system_info.c system_time_asm.S thread.c - time.c + time.cpp tls.c $(compatibilitySources) diff --git a/src/system/libroot/os/arch/x86/time.c b/src/system/libroot/os/arch/x86/time.cpp similarity index 100% rename from src/system/libroot/os/arch/x86/time.c rename to src/system/libroot/os/arch/x86/time.cpp From d38f1301d1e3f4c56f6350b40be3275ceff478ee Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 13:55:03 +0100 Subject: [PATCH 099/273] Cleaned up 32-bit descriptors.h. --- .../private/kernel/arch/x86/32/descriptors.h | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h index 81fd842e8d..e09b849e3a 100644 --- a/headers/private/kernel/arch/x86/32/descriptors.h +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -21,6 +21,7 @@ #define BIOS_DATA_SEGMENT 0x40 + #ifndef _ASSEMBLER // this file can also be included from assembler as well // (and is in arch_interrupts.S) @@ -34,7 +35,7 @@ // defines entries in the GDT/LDT -typedef struct segment_descriptor { +struct segment_descriptor { uint16 limit_00_15; // bit 0 - 15 uint16 base_00_15; // 16 - 31 uint32 base_23_16 : 8; // 0 - 7 @@ -48,11 +49,12 @@ typedef struct segment_descriptor { uint32 d_b : 1; // 22 uint32 granularity : 1; // 23 uint32 base_31_24 : 8; // 24 - 31 -} segment_descriptor; +}; -typedef struct interrupt_descriptor { - uint32 a, b; -} interrupt_descriptor; +struct interrupt_descriptor { + uint32 a; + uint32 b; +}; struct tss { uint16 prev_task; @@ -73,14 +75,14 @@ struct tss { static inline void -clear_segment_descriptor(struct segment_descriptor *desc) +clear_segment_descriptor(segment_descriptor* desc) { - *(long long *)desc = 0; + *(long long*)desc = 0; } static inline void -set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) +set_segment_descriptor_base(segment_descriptor* desc, addr_t base) { desc->base_00_15 = (addr_t)base & 0xffff; // base is 32 bits long desc->base_23_16 = ((addr_t)base >> 16) & 0xff; @@ -89,7 +91,7 @@ set_segment_descriptor_base(struct segment_descriptor *desc, addr_t base) static inline void -set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit, +set_segment_descriptor(segment_descriptor* desc, addr_t base, uint32 limit, uint8 type, uint8 privilegeLevel) { set_segment_descriptor_base(desc, base); @@ -104,8 +106,6 @@ set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limi desc->limit_19_16 = ((addr_t)limit >> 16) & 0xf; desc->granularity = 0; // 1 byte granularity } - limit >>= 12; - desc->type = type; desc->desc_type = DT_CODE_DATA_SEGMENT; @@ -120,7 +120,7 @@ set_segment_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limi static inline void -set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) +set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit) { // the TSS descriptor has a special layout different from the standard descriptor set_segment_descriptor_base(desc, base); @@ -140,6 +140,7 @@ set_tss_descriptor(struct segment_descriptor *desc, addr_t base, uint32 limit) desc->zero = 0; } + #endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ From 6e06fa6f7ea099cec5247fa2e8409c9c8ab3c983 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 14:06:29 +0100 Subject: [PATCH 100/273] Added missing validity check on relocation address. --- src/system/kernel/arch/x86/arch_elf.cpp | 32 +++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_elf.cpp b/src/system/kernel/arch/x86/arch_elf.cpp index fee26732a5..111329a3c2 100644 --- a/src/system/kernel/arch/x86/arch_elf.cpp +++ b/src/system/kernel/arch/x86/arch_elf.cpp @@ -25,6 +25,18 @@ #endif +#ifndef _BOOT_MODE +static bool +is_in_image(struct elf_image_info *image, addr_t address) +{ + return (address >= image->text_region.start + && address < image->text_region.start + image->text_region.size) + || (address >= image->data_region.start + && address < image->data_region.start + image->data_region.size); +} +#endif // !_BOOT_MODE + + #if !defined(__x86_64__) || defined(_BOOT_MODE) @@ -45,18 +57,6 @@ static const char *kRelocations[] = { #endif -#ifndef _BOOT_MODE -static bool -is_in_image(struct elf_image_info *image, addr_t address) -{ - return (address >= image->text_region.start - && address < image->text_region.start + image->text_region.size) - || (address >= image->data_region.start - && address < image->data_region.start + image->data_region.size); -} -#endif // !_BOOT_MODE - - #ifdef _BOOT_MODE status_t boot_arch_elf_relocate_rel(struct preloaded_elf32_image *image, @@ -255,13 +255,19 @@ arch_elf_relocate_rela(struct elf_image_info *image, relocValue = image->text_region.delta + rel[i].r_addend; break; default: - dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", + dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", type); return B_BAD_DATA; } #ifdef _BOOT_MODE boot_elf64_set_relocation(relocAddr, relocValue); #else + if (!is_in_image(image, relocAddr)) { + dprintf("arch_elf_relocate_rela: invalid offset %#lx\n", + rel[i].r_offset); + return B_BAD_ADDRESS; + } + *(Elf64_Addr *)relocAddr = relocValue; #endif } From 4ebc6dfa682fa199a88ec06f0930df04369f34ac Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 14:23:55 +0100 Subject: [PATCH 101/273] Moved some 32-bit specific stuff to the 32 subdirectory. --- headers/private/kernel/arch/x86/bios.h | 4 ++++ src/system/kernel/arch/x86/{ => 32}/apm.cpp | 0 src/system/kernel/arch/x86/{ => 32}/bios.cpp | 0 src/system/kernel/arch/x86/{ => 32}/vm86.cpp | 0 src/system/kernel/arch/x86/Jamfile | 6 +++--- 5 files changed, 7 insertions(+), 3 deletions(-) rename src/system/kernel/arch/x86/{ => 32}/apm.cpp (100%) rename src/system/kernel/arch/x86/{ => 32}/bios.cpp (100%) rename src/system/kernel/arch/x86/{ => 32}/vm86.cpp (100%) diff --git a/headers/private/kernel/arch/x86/bios.h b/headers/private/kernel/arch/x86/bios.h index c88fe772dd..145f08fbf9 100644 --- a/headers/private/kernel/arch/x86/bios.h +++ b/headers/private/kernel/arch/x86/bios.h @@ -9,6 +9,8 @@ #include +#ifndef __x86_64__ + #define BIOS32_PCI_SERVICE 'ICP$' struct bios32_service { @@ -29,4 +31,6 @@ status_t bios_init(void); } #endif +#endif /* __x86_64__ */ + #endif /* ARCH_x86_BIOS_H */ diff --git a/src/system/kernel/arch/x86/apm.cpp b/src/system/kernel/arch/x86/32/apm.cpp similarity index 100% rename from src/system/kernel/arch/x86/apm.cpp rename to src/system/kernel/arch/x86/32/apm.cpp diff --git a/src/system/kernel/arch/x86/bios.cpp b/src/system/kernel/arch/x86/32/bios.cpp similarity index 100% rename from src/system/kernel/arch/x86/bios.cpp rename to src/system/kernel/arch/x86/32/bios.cpp diff --git a/src/system/kernel/arch/x86/vm86.cpp b/src/system/kernel/arch/x86/32/vm86.cpp similarity index 100% rename from src/system/kernel/arch/x86/vm86.cpp rename to src/system/kernel/arch/x86/32/vm86.cpp diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 8834924481..2d4150920a 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -41,22 +41,22 @@ if $(TARGET_ARCH) = x86_64 { SEARCH_SOURCE += [ FDirName $(SUBDIR) paging pae ] ; archSpecificSources = + apm.cpp arch.S + bios.cpp cpuid.S int.cpp interrupts.S thread.cpp + vm86.cpp arch_commpage.cpp arch_debug.cpp arch_user_debugger.cpp - apm.cpp - bios.cpp ioapic.cpp irq_routing_table.cpp msi.cpp syscall.S - vm86.cpp x86_signals.cpp x86_signals_asm.S x86_syscalls.cpp From e690e5ab3b4adc583b94a27400b7fd12da80ce51 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 12 Jul 2012 17:16:17 +0100 Subject: [PATCH 102/273] Proper fix for GCC 2 compilation error that was fixed earlier, cause pointed out by Ingo. --- src/system/boot/platform/bios_ia32/smp.cpp | 4 ++-- src/system/boot/platform/bios_ia32/smp.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index ef9545344c..d0d2c65eb3 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -420,8 +420,8 @@ smp_init_other_cpus(void) } -extern "C" void -smp_boot_other_cpus(void (*entryFunc)()) +void +smp_boot_other_cpus(void (*entryFunc)(void)) { if (gKernelArgs.num_cpus < 2) return; diff --git a/src/system/boot/platform/bios_ia32/smp.h b/src/system/boot/platform/bios_ia32/smp.h index 2380e63072..4acda1622d 100644 --- a/src/system/boot/platform/bios_ia32/smp.h +++ b/src/system/boot/platform/bios_ia32/smp.h @@ -19,7 +19,7 @@ extern "C" { extern void smp_init(void); extern void smp_init_other_cpus(void); -extern void smp_boot_other_cpus(void (*entryFunc)()); +extern void smp_boot_other_cpus(void (*entryFunc)(void)); extern int smp_get_current_cpu(void); From bcb07a319b647eb0af60398e972525cc0a686aa9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 13 Jul 2012 14:09:09 +0100 Subject: [PATCH 103/273] Implemented the rest of the kernel debugger functions for x86_64. Merged with the x86 implementations, mostly the same except for a few differences. GDB stub is currently broken, will investigate later. --- headers/private/kernel/arch/x86/64/iframe.h | 13 +- .../kernel/arch/x86/arch_thread_types.h | 26 +- src/system/kernel/arch/x86/64/stubs.cpp | 209 -------- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_debug.cpp | 498 +++++++++++------- src/system/kernel/arch/x86/arch_thread.cpp | 12 +- 6 files changed, 336 insertions(+), 424 deletions(-) diff --git a/headers/private/kernel/arch/x86/64/iframe.h b/headers/private/kernel/arch/x86/64/iframe.h index cd257ef6ea..ff0dae74be 100644 --- a/headers/private/kernel/arch/x86/64/iframe.h +++ b/headers/private/kernel/arch/x86/64/iframe.h @@ -29,9 +29,16 @@ struct iframe { uint64 cs; uint64 flags; - // Only present when the iframe is a userland iframe (IFRAME_IS_USER()). - uint64 user_sp; - uint64 user_ss; + // SP and SS are unconditionally present on x86_64, make both names + // available. + union { + uint64 sp; + uint64 user_sp; + }; + union { + uint64 ss; + uint64 user_ss; + }; } _PACKED; #define IFRAME_IS_USER(f) (((f)->cs & DPL_USER) == DPL_USER) diff --git a/headers/private/kernel/arch/x86/arch_thread_types.h b/headers/private/kernel/arch/x86/arch_thread_types.h index 209543e7ba..85dfc6bb08 100644 --- a/headers/private/kernel/arch/x86/arch_thread_types.h +++ b/headers/private/kernel/arch/x86/arch_thread_types.h @@ -48,6 +48,8 @@ struct arch_thread { // 512 byte floating point save point - this must be 16 byte aligned uint8 fpu_state[512] _ALIGNED(16); + + addr_t GetFramePointer() const; } _ALIGNED(16); @@ -64,4 +66,26 @@ struct arch_fork_arg { }; -#endif /* _KERNEL_ARCH_x86_THREAD_TYPES_H */ +#ifdef __x86_64__ + + +inline addr_t +arch_thread::GetFramePointer() const +{ + return current_stack[1]; +} + + +#else + + +inline addr_t +arch_thread::GetFramePointer() const +{ + return current_stack.esp[2]; +} + + +#endif // __x86_64__ + +#endif // _KERNEL_ARCH_x86_THREAD_TYPES_H diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 72b95c6449..b8efb2ff25 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -51,215 +51,6 @@ arch_commpage_init_post_cpus(void) } -void -arch_debug_save_registers(struct arch_debug_registers* registers) -{ - -} - - -struct stack_frame { - struct stack_frame *previous; - addr_t return_address; -}; - - -static bool -is_iframe(addr_t frame) -{ - addr_t previousFrame = *(addr_t*)frame; - return ((previousFrame & ~(addr_t)IFRAME_TYPE_MASK) == 0 - && previousFrame != 0); -} - - -static void -print_iframe(struct iframe* frame) -{ - bool isUser = IFRAME_IS_USER(frame); - - kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, - isUser ? (uint64*)(frame + 1) : &frame->user_sp); - - kprintf(" rax 0x%-16lx rbx 0x%-16lx rcx 0x%lx\n", frame->ax, - frame->bx, frame->cx); - kprintf(" rdx 0x%-16lx rsi 0x%-16lx rdi 0x%lx\n", frame->dx, - frame->si, frame->di); - kprintf(" rbp 0x%-16lx r8 0x%-16lx r9 0x%lx\n", frame->bp, - frame->r8, frame->r9); - kprintf(" r10 0x%-16lx r11 0x%-16lx r12 0x%lx\n", frame->r10, - frame->r11, frame->r12); - kprintf(" r13 0x%-16lx r14 0x%-16lx r15 0x%lx\n", frame->r13, - frame->r14, frame->r15); - kprintf(" rip 0x%-16lx rflags 0x%-16lx", frame->ip, frame->flags); - - if (isUser) { - // from user space - kprintf("user rsp 0x%lx", frame->user_sp); - } - kprintf("\n"); - kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, - frame->error_code); -} - - -static status_t -lookup_symbol(addr_t address, addr_t* _baseAddress, const char** _symbolName, - const char** _imageName, bool* _exactMatch) -{ - status_t status = B_ENTRY_NOT_FOUND; - - if (IS_KERNEL_ADDRESS(address)) { - status = elf_debug_lookup_symbol_address(address, _baseAddress, - _symbolName, _imageName, _exactMatch); - } - - return status; -} - - -static void -print_stack_frame(addr_t rip, addr_t rbp, addr_t nextRbp, int32 callIndex) -{ - const char* symbol; - const char* image; - addr_t baseAddress; - bool exactMatch; - status_t status; - addr_t diff; - - diff = nextRbp - rbp; - - // kernel space/user space switch - if (diff & (1L << 63)) - diff = 0; - - status = lookup_symbol(rip, &baseAddress, &symbol, &image, &exactMatch); - - kprintf("%2d %016lx (+%4ld) %016lx ", callIndex, rbp, diff, rip); - - if (status == B_OK) { - if (symbol != NULL) - kprintf("<%s>:%s%s", image, symbol, exactMatch ? "" : " (nearest)"); - else - kprintf("<%s@%p>:unknown", image, (void*)baseAddress); - - kprintf(" + 0x%04lx\n", rip - baseAddress); - } else { - VMArea *area = VMAddressSpace::Kernel()->LookupArea(rip); - if (area != NULL) { - kprintf("%d:%s@%p + %#lx\n", area->id, area->name, - (void*)area->Base(), rip - area->Base()); - } else - kprintf("\n"); - } -} - - -void -arch_debug_stack_trace(void) -{ - addr_t rbp = x86_get_stack_frame(); - - kprintf("frame caller :function" - " + offset\n"); - - for (int32 callIndex = 0;; callIndex++) { - if (rbp == 0) - break; - - if (is_iframe(rbp)) { - struct iframe* frame = (struct iframe*)rbp; - print_iframe(frame); - print_stack_frame(frame->ip, rbp, frame->bp, callIndex); - - rbp = frame->bp; - } else { - stack_frame* frame = (stack_frame*)rbp; - if (frame->return_address == 0) - break; - - print_stack_frame(frame->return_address, rbp, - (frame->previous != NULL) ? (addr_t)frame->previous : rbp, - callIndex); - - rbp = (addr_t)frame->previous; - } - } -} - - -bool -arch_debug_contains_call(Thread *thread, const char *symbol, - addr_t start, addr_t end) -{ - return false; -} - - -void * -arch_debug_get_caller(void) -{ - return NULL; -} - - -int32 -arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, - int32 skipIframes, int32 skipFrames, uint32 flags) -{ - return 0; -} - - -void* -arch_debug_get_interrupt_pc(bool* _isSyscall) -{ - return NULL; -} - - -void -arch_debug_unset_current_thread(void) -{ - -} - - -bool -arch_is_debug_variable_defined(const char* variableName) -{ - return false; -} - - -status_t -arch_set_debug_variable(const char* variableName, uint64 value) -{ - return B_OK; -} - - -status_t -arch_get_debug_variable(const char* variableName, uint64* value) -{ - return B_OK; -} - - -ssize_t -arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) -{ - return B_ERROR; -} - - -status_t -arch_debug_init(kernel_args *args) -{ - return B_OK; -} - void arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, void (*function)(void*), void* parameter) diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 2d4150920a..9b1a888578 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -51,7 +51,6 @@ if $(TARGET_ARCH) = x86_64 { vm86.cpp arch_commpage.cpp - arch_debug.cpp arch_user_debugger.cpp ioapic.cpp irq_routing_table.cpp @@ -78,6 +77,7 @@ if $(TARGET_ARCH) = x86_64 { local archGenericSources = arch_cpu.cpp + arch_debug.cpp arch_debug_console.cpp arch_elf.cpp arch_int.cpp diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index 9d21c7bcc6..0f3faa82a5 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -1,6 +1,7 @@ /* * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. * Distributed under the terms of the MIT License. * * Copyright 2001, Travis Geiselbrecht. All rights reserved. @@ -28,31 +29,29 @@ #include #include -#include - struct stack_frame { - struct stack_frame *previous; - addr_t return_address; + stack_frame* previous; + addr_t return_address; }; #define NUM_PREVIOUS_LOCATIONS 32 static bool -already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) +already_visited(addr_t* visited, int32* _last, int32* _num, addr_t bp) { int32 last = *_last; int32 num = *_num; int32 i; for (i = 0; i < num; i++) { - if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == ebp) + if (visited[(NUM_PREVIOUS_LOCATIONS + last - i) % NUM_PREVIOUS_LOCATIONS] == bp) return true; } *_last = last = (last + 1) % NUM_PREVIOUS_LOCATIONS; - visited[last] = ebp; + visited[last] = bp; if (num < NUM_PREVIOUS_LOCATIONS) *_num = num + 1; @@ -64,14 +63,14 @@ already_visited(uint32 *visited, int32 *_last, int32 *_num, uint32 ebp) /*! Safe to be called only from outside the debugger. */ static status_t -get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) +get_next_frame_no_debugger(addr_t bp, addr_t* _next, addr_t* _ip) { // TODO: Do this more efficiently in assembly. stack_frame frame; - if (user_memcpy(&frame, (void*)ebp, sizeof(frame)) != B_OK) + if (user_memcpy(&frame, (void*)bp, sizeof(frame)) != B_OK) return B_BAD_ADDRESS; - *_eip = frame.return_address; + *_ip = frame.return_address; *_next = (addr_t)frame.previous; return B_OK; @@ -81,13 +80,13 @@ get_next_frame_no_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) /*! Safe to be called only from inside the debugger. */ static status_t -get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) +get_next_frame_debugger(addr_t bp, addr_t* _next, addr_t* _ip) { stack_frame frame; - if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)ebp, sizeof(frame)) != B_OK) + if (debug_memcpy(B_CURRENT_TEAM, &frame, (void*)bp, sizeof(frame)) != B_OK) return B_BAD_ADDRESS; - *_eip = frame.return_address; + *_ip = frame.return_address; *_next = (addr_t)frame.previous; return B_OK; @@ -95,8 +94,8 @@ get_next_frame_debugger(addr_t ebp, addr_t *_next, addr_t *_eip) static status_t -lookup_symbol(Thread* thread, addr_t address, addr_t *_baseAddress, - const char **_symbolName, const char **_imageName, bool *_exactMatch) +lookup_symbol(Thread* thread, addr_t address, addr_t* _baseAddress, + const char** _symbolName, const char** _imageName, bool* _exactMatch) { status_t status = B_ENTRY_NOT_FOUND; @@ -120,6 +119,9 @@ lookup_symbol(Thread* thread, addr_t address, addr_t *_baseAddress, } +#ifndef __x86_64__ + + static void set_debug_argument_variable(int32 index, uint64 value) { @@ -307,31 +309,53 @@ print_demangled_call(const char* image, const char* symbol, addr_t args, } +#else // __x86_64__ + + +static status_t +print_demangled_call(const char* image, const char* symbol, addr_t args, + bool noObjectMethod, bool addDebugVariables) +{ + // Since x86_64 uses registers rather than the stack for the first 6 + // arguments we cannot use the same method as x86 to read the function + // arguments. Maybe we need DWARF support in the kernel debugger. For now + // just print out the function signature without the argument values. + + // TODO x86_64. + return B_NOT_SUPPORTED; +} + + +#endif // __x86_64__ + + static void -print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, +print_stack_frame(Thread* thread, addr_t ip, addr_t bp, addr_t nextBp, int32 callIndex, bool demangle) { - const char *symbol, *image; + const char* symbol; + const char* image; addr_t baseAddress; bool exactMatch; status_t status; addr_t diff; - diff = nextEbp - ebp; + diff = nextBp - bp; - // kernel space/user space switch - if (diff & 0x80000000) + // MSB set = kernel space/user space switch + if (diff & ~((addr_t)-1 >> 1)) diff = 0; - status = lookup_symbol(thread, eip, &baseAddress, &symbol, &image, + status = lookup_symbol(thread, ip, &baseAddress, &symbol, &image, &exactMatch); - kprintf("%2ld %08lx (+%4ld) %08lx ", callIndex, ebp, diff, eip); + kprintf("%2" B_PRId32 " %0*lx (+%4ld) %0*lx ", callIndex, + B_PRINTF_POINTER_WIDTH, bp, diff, B_PRINTF_POINTER_WIDTH, ip); if (status == B_OK) { if (exactMatch && demangle) { - status = print_demangled_call(image, symbol, nextEbp + 8, false, - false); + status = print_demangled_call(image, symbol, + nextBp + sizeof(stack_frame), false, false); } if (!exactMatch || !demangle || status != B_OK) { @@ -339,19 +363,19 @@ print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, kprintf("<%s>:%s%s", image, symbol, exactMatch ? "" : " (nearest)"); } else - kprintf("<%s@%p>:unknown", image, (void *)baseAddress); + kprintf("<%s@%p>:unknown", image, (void*)baseAddress); } - kprintf(" + 0x%04lx\n", eip - baseAddress); + kprintf(" + %#04lx\n", ip - baseAddress); } else { VMArea *area = NULL; if (thread != NULL && thread->team != NULL && thread->team->address_space != NULL) { - area = thread->team->address_space->LookupArea(eip); + area = thread->team->address_space->LookupArea(ip); } if (area != NULL) { - kprintf("%ld:%s@%p + %#lx\n", area->id, area->name, - (void*)area->Base(), eip - area->Base()); + kprintf("%" B_PRId32 ":%s@%p + %#lx\n", area->id, area->name, + (void*)area->Base(), ip - area->Base()); } else kprintf("\n"); } @@ -359,45 +383,65 @@ print_stack_frame(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, static void -print_iframe(struct iframe *frame) +print_iframe(iframe* frame) { bool isUser = IFRAME_IS_USER(frame); - kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, - isUser ? (uint32*)(frame + 1) : &frame->user_sp); - kprintf(" eax 0x%-9lx ebx 0x%-9lx ecx 0x%-9lx edx 0x%lx\n", +#ifdef __x86_64__ + kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, + frame + 1); + + kprintf(" rax %#-18lx rbx %#-18lx rcx %#lx\n", frame->ax, + frame->bx, frame->cx); + kprintf(" rdx %#-18lx rsi %#-18lx rdi %#lx\n", frame->dx, + frame->si, frame->di); + kprintf(" rbp %#-18lx r8 %#-18lx r9 %#lx\n", frame->bp, + frame->r8, frame->r9); + kprintf(" r10 %#-18lx r11 %#-18lx r12 %#lx\n", frame->r10, + frame->r11, frame->r12); + kprintf(" r13 %#-18lx r14 %#-18lx r15 %#lx\n", frame->r13, + frame->r14, frame->r15); + kprintf(" rip %#-18lx rsp %#-18lx rflags %#lx\n", frame->ip, + frame->sp, frame->flags); +#else + kprintf("%s iframe at %p (end = %p)\n", isUser ? "user" : "kernel", frame, + isUser ? (void*)(frame + 1) : (void*)&frame->user_sp); + + kprintf(" eax %#-10lx ebx %#-10lx ecx %#-10lx edx %#lx\n", frame->ax, frame->bx, frame->cx, frame->dx); - kprintf(" esi 0x%-9lx edi 0x%-9lx ebp 0x%-9lx esp 0x%lx\n", + kprintf(" esi %#-10lx edi %#-10lx ebp %#-10lx esp %#lx\n", frame->si, frame->di, frame->bp, frame->sp); - kprintf(" eip 0x%-9lx eflags 0x%-9lx", frame->ip, frame->flags); + kprintf(" eip %#-10lx eflags %#-10lx", frame->ip, frame->flags); if (isUser) { // from user space - kprintf("user esp 0x%lx", frame->user_sp); + kprintf("user esp %#lx", frame->user_sp); } kprintf("\n"); - kprintf(" vector: 0x%lx, error code: 0x%lx\n", frame->vector, +#endif + + kprintf(" vector: %#lx, error code: %#lx\n", frame->vector, frame->error_code); } static bool -setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp, - uint32 *_oldPageDirectory) +setup_for_thread(char* arg, Thread** _thread, addr_t* _bp, + phys_addr_t* _oldPageDirectory) { - Thread *thread = NULL; + Thread* thread = NULL; if (arg != NULL) { thread_id id = strtoul(arg, NULL, 0); thread = Thread::GetDebug(id); if (thread == NULL) { - kprintf("could not find thread %ld\n", id); + kprintf("could not find thread %" B_PRId32 "\n", id); return false; } if (id != thread_get_current_thread_id()) { // switch to the page directory of the new thread to be // able to follow the stack trace into userland - uint32 newPageDirectory = x86_next_page_directory( + phys_addr_t newPageDirectory = x86_next_page_directory( thread_get_current_thread(), thread); if (newPageDirectory != 0) { @@ -413,10 +457,10 @@ setup_for_thread(char *arg, Thread **_thread, uint32 *_ebp, thread->cpu->cpu_num); if (registers == NULL) return false; - *_ebp = registers->bp; + *_bp = registers->bp; } else { - // read %ebp from the thread's stack stored by a pushad - *_ebp = thread->arch_info.current_stack.esp[2]; + // Read frame pointer from the thread's stack. + *_bp = thread->arch_info.GetFramePointer(); } } else thread = NULL; @@ -474,13 +518,13 @@ is_iframe(Thread* thread, addr_t frame) } -static struct iframe * -find_previous_iframe(Thread *thread, addr_t frame) +static iframe* +find_previous_iframe(Thread* thread, addr_t frame) { // iterate backwards through the stack frames, until we hit an iframe while (is_kernel_stack_address(thread, frame)) { if (is_iframe(thread, frame)) - return (struct iframe*)frame; + return (iframe*)frame; frame = *(addr_t*)frame; } @@ -489,8 +533,8 @@ find_previous_iframe(Thread *thread, addr_t frame) } -static struct iframe* -get_previous_iframe(Thread* thread, struct iframe* frame) +static iframe* +get_previous_iframe(Thread* thread, iframe* frame) { if (frame == NULL) return NULL; @@ -499,90 +543,83 @@ get_previous_iframe(Thread* thread, struct iframe* frame) } -static struct iframe* +static iframe* get_current_iframe(Thread* thread) { if (thread == thread_get_current_thread()) return x86_get_current_iframe(); - addr_t ebp = thread->arch_info.current_stack.esp[2]; - // NOTE: This doesn't work, if the thread is running (on another CPU). - return find_previous_iframe(thread, ebp); + // NOTE: This doesn't work, if the thread is running (on another CPU). + return find_previous_iframe(thread, thread->arch_info.GetFramePointer()); } -uint32* +#define CHECK_DEBUG_VARIABLE(_name, _member, _settable) \ + if (strcmp(variableName, _name) == 0) { \ + settable = _settable; \ + return &_member; \ + } + + +static size_t* find_debug_variable(const char* variableName, bool& settable) { - struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); + iframe* frame = get_current_iframe(debug_get_debugged_thread()); if (frame == NULL) return NULL; - settable = false; - - if (strcmp(variableName, "gs") == 0) { - return &frame->gs; - } else if (strcmp(variableName, "fs") == 0) { - return &frame->fs; - } else if (strcmp(variableName, "es") == 0) { - return &frame->es; - } else if (strcmp(variableName, "ds") == 0) { - return &frame->ds; - } else if (strcmp(variableName, "cs") == 0) { - return &frame->cs; - } else if (strcmp(variableName, "edi") == 0) { - settable = true; - return &frame->di; - } else if (strcmp(variableName, "esi") == 0) { - settable = true; - return &frame->si; - } else if (strcmp(variableName, "ebp") == 0) { - settable = true; - return &frame->bp; - } else if (strcmp(variableName, "esp") == 0) { - settable = true; - return &frame->sp; - } else if (strcmp(variableName, "ebx") == 0) { - settable = true; - return &frame->bx; - } else if (strcmp(variableName, "edx") == 0) { - settable = true; - return &frame->dx; - } else if (strcmp(variableName, "ecx") == 0) { - settable = true; - return &frame->cx; - } else if (strcmp(variableName, "eax") == 0) { - settable = true; - return &frame->ax; - } else if (strcmp(variableName, "orig_eax") == 0) { - settable = true; - return &frame->orig_eax; - } else if (strcmp(variableName, "orig_edx") == 0) { - settable = true; - return &frame->orig_edx; - } else if (strcmp(variableName, "eip") == 0) { - settable = true; - return &frame->ip; - } else if (strcmp(variableName, "eflags") == 0) { - settable = true; - return &frame->flags; - } +#ifdef __x86_64__ + CHECK_DEBUG_VARIABLE("cs", frame->cs, false); + CHECK_DEBUG_VARIABLE("ss", frame->ss, false); + CHECK_DEBUG_VARIABLE("r15", frame->r15, true); + CHECK_DEBUG_VARIABLE("r14", frame->r14, true); + CHECK_DEBUG_VARIABLE("r13", frame->r13, true); + CHECK_DEBUG_VARIABLE("r12", frame->r12, true); + CHECK_DEBUG_VARIABLE("r11", frame->r11, true); + CHECK_DEBUG_VARIABLE("r10", frame->r10, true); + CHECK_DEBUG_VARIABLE("r9", frame->r9, true); + CHECK_DEBUG_VARIABLE("r8", frame->r8, true); + CHECK_DEBUG_VARIABLE("rbp", frame->bp, true); + CHECK_DEBUG_VARIABLE("rsi", frame->si, true); + CHECK_DEBUG_VARIABLE("rdi", frame->di, true); + CHECK_DEBUG_VARIABLE("rdx", frame->dx, true); + CHECK_DEBUG_VARIABLE("rcx", frame->cx, true); + CHECK_DEBUG_VARIABLE("rbx", frame->bx, true); + CHECK_DEBUG_VARIABLE("rax", frame->ax, true); + CHECK_DEBUG_VARIABLE("rip", frame->ip, true); + CHECK_DEBUG_VARIABLE("rflags", frame->flags, true); + CHECK_DEBUG_VARIABLE("rsp", frame->sp, true); +#else + CHECK_DEBUG_VARIABLE("gs", frame->gs, false); + CHECK_DEBUG_VARIABLE("fs", frame->fs, false); + CHECK_DEBUG_VARIABLE("es", frame->es, false); + CHECK_DEBUG_VARIABLE("ds", frame->ds, false); + CHECK_DEBUG_VARIABLE("cs", frame->cs, false); + CHECK_DEBUG_VARIABLE("edi", frame->di, true); + CHECK_DEBUG_VARIABLE("esi", frame->si, true); + CHECK_DEBUG_VARIABLE("ebp", frame->bp, true); + CHECK_DEBUG_VARIABLE("esp", frame->sp, true); + CHECK_DEBUG_VARIABLE("ebx", frame->bx, true); + CHECK_DEBUG_VARIABLE("edx", frame->dx, true); + CHECK_DEBUG_VARIABLE("ecx", frame->cx, true); + CHECK_DEBUG_VARIABLE("eax", frame->ax, true); + CHECK_DEBUG_VARIABLE("orig_eax", frame->orig_eax, true); + CHECK_DEBUG_VARIABLE("orig_edx", frame->orig_edx, true); + CHECK_DEBUG_VARIABLE("eip", frame->ip, true); + CHECK_DEBUG_VARIABLE("eflags", frame->flags, true); if (IFRAME_IS_USER(frame)) { - if (strcmp(variableName, "user_esp") == 0) { - settable = true; - return &frame->user_sp; - } else if (strcmp(variableName, "user_ss") == 0) { - return &frame->user_ss; - } + CHECK_DEBUG_VARIABLE("user_esp", frame->user_sp, true); + CHECK_DEBUG_VARIABLE("user_ss", frame->user_ss, false); } +#endif return NULL; } static int -stack_trace(int argc, char **argv) +stack_trace(int argc, char** argv) { static const char* usage = "usage: %s [-d] [ ]\n" "Prints a stack trace for the current, respectively the specified\n" @@ -603,68 +640,69 @@ stack_trace(int argc, char **argv) return 0; } - uint32 previousLocations[NUM_PREVIOUS_LOCATIONS]; - Thread *thread = NULL; - uint32 oldPageDirectory = 0; - uint32 ebp = x86_get_stack_frame(); + addr_t previousLocations[NUM_PREVIOUS_LOCATIONS]; + Thread* thread = NULL; + phys_addr_t oldPageDirectory = 0; + addr_t bp = x86_get_stack_frame(); int32 num = 0, last = 0; if (!setup_for_thread(argc == threadIndex + 1 ? argv[threadIndex] : NULL, - &thread, &ebp, &oldPageDirectory)) + &thread, &bp, &oldPageDirectory)) return 0; DebuggedThreadSetter threadSetter(thread); if (thread != NULL) { - kprintf("stack trace for thread %ld \"%s\"\n", thread->id, + kprintf("stack trace for thread %" B_PRId32 " \"%s\"\n", thread->id, thread->name); kprintf(" kernel stack: %p to %p\n", - (void *)thread->kernel_stack_base, - (void *)(thread->kernel_stack_top)); + (void*)thread->kernel_stack_base, + (void*)(thread->kernel_stack_top)); if (thread->user_stack_base != 0) { kprintf(" user stack: %p to %p\n", - (void *)thread->user_stack_base, - (void *)(thread->user_stack_base + thread->user_stack_size)); + (void*)thread->user_stack_base, + (void*)(thread->user_stack_base + thread->user_stack_size)); } } - kprintf("frame caller :function + offset\n"); + kprintf("%-*s %-*s :function + offset\n", + B_PRINTF_POINTER_WIDTH, "frame", B_PRINTF_POINTER_WIDTH, "caller"); bool onKernelStack = true; for (int32 callIndex = 0;; callIndex++) { onKernelStack = onKernelStack - && is_kernel_stack_address(thread, ebp); + && is_kernel_stack_address(thread, bp); - if (onKernelStack && is_iframe(thread, ebp)) { - struct iframe *frame = (struct iframe *)ebp; + if (onKernelStack && is_iframe(thread, bp)) { + iframe* frame = (iframe*)bp; print_iframe(frame); - print_stack_frame(thread, frame->ip, ebp, frame->bp, callIndex, + print_stack_frame(thread, frame->ip, bp, frame->bp, callIndex, demangle); - ebp = frame->bp; + bp = frame->bp; } else { - addr_t eip, nextEbp; + addr_t ip, nextBp; - if (get_next_frame_debugger(ebp, &nextEbp, &eip) != B_OK) { - kprintf("%08lx -- read fault\n", ebp); + if (get_next_frame_debugger(bp, &nextBp, &ip) != B_OK) { + kprintf("%0*lx -- read fault\n", B_PRINTF_POINTER_WIDTH, bp); break; } - if (eip == 0 || ebp == 0) + if (ip == 0 || bp == 0) break; - print_stack_frame(thread, eip, ebp, nextEbp, callIndex, demangle); - ebp = nextEbp; + print_stack_frame(thread, ip, bp, nextBp, callIndex, demangle); + bp = nextBp; } - if (already_visited(previousLocations, &last, &num, ebp)) { - kprintf("circular stack frame: %p!\n", (void *)ebp); + if (already_visited(previousLocations, &last, &num, bp)) { + kprintf("circular stack frame: %p!\n", (void*)bp); break; } - if (ebp == 0) + if (bp == 0) break; } @@ -677,6 +715,7 @@ stack_trace(int argc, char **argv) } +#ifndef __x86_64__ static void print_call(Thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp, int32 argCount) @@ -759,7 +798,7 @@ show_call(int argc, char **argv) } Thread *thread = NULL; - uint32 oldPageDirectory = 0; + phys_addr_t oldPageDirectory = 0; addr_t ebp = x86_get_stack_frame(); int32 argCount = 0; @@ -835,10 +874,11 @@ show_call(int argc, char **argv) return 0; } +#endif static int -dump_iframes(int argc, char **argv) +dump_iframes(int argc, char** argv) { static const char* usage = "usage: %s [ ]\n" "Prints the iframe stack for the current, respectively the specified\n" @@ -850,7 +890,7 @@ dump_iframes(int argc, char **argv) return 0; } - Thread *thread = NULL; + Thread* thread = NULL; if (argc < 2) { thread = thread_get_current_thread(); @@ -858,7 +898,7 @@ dump_iframes(int argc, char **argv) thread_id id = strtoul(argv[1], NULL, 0); thread = Thread::GetDebug(id); if (thread == NULL) { - kprintf("could not find thread %ld\n", id); + kprintf("could not find thread %" B_PRId32 "\n", id); return 0; } } else if (argc > 2) { @@ -866,12 +906,14 @@ dump_iframes(int argc, char **argv) return 0; } - if (thread != NULL) - kprintf("iframes for thread %ld \"%s\"\n", thread->id, thread->name); + if (thread != NULL) { + kprintf("iframes for thread %" B_PRId32 " \"%s\"\n", thread->id, + thread->name); + } DebuggedThreadSetter threadSetter(thread); - struct iframe* frame = find_previous_iframe(thread, x86_get_stack_frame()); + iframe* frame = find_previous_iframe(thread, x86_get_stack_frame()); while (frame != NULL) { print_iframe(frame); frame = get_previous_iframe(thread, frame); @@ -882,17 +924,17 @@ dump_iframes(int argc, char **argv) static bool -is_calling(Thread *thread, addr_t eip, const char *pattern, - addr_t start, addr_t end) +is_calling(Thread* thread, addr_t ip, const char* pattern, addr_t start, + addr_t end) { if (pattern == NULL) - return eip >= start && eip < end; + return ip >= start && ip < end; - if (!IS_KERNEL_ADDRESS(eip)) + if (!IS_KERNEL_ADDRESS(ip)) return false; - const char *symbol; - if (lookup_symbol(thread, eip, NULL, &symbol, NULL, NULL) != B_OK) + const char* symbol; + if (lookup_symbol(thread, ip, NULL, &symbol, NULL, NULL) != B_OK) return false; return strstr(symbol, pattern); @@ -933,9 +975,9 @@ cmd_in_context(int argc, char** argv) } // switch the page directory, if necessary - uint32 oldPageDirectory = 0; + phys_addr_t oldPageDirectory = 0; if (thread != thread_get_current_thread()) { - uint32 newPageDirectory = x86_next_page_directory( + phys_addr_t newPageDirectory = x86_next_page_directory( thread_get_current_thread(), thread); if (newPageDirectory != 0) { @@ -962,7 +1004,7 @@ cmd_in_context(int argc, char** argv) void -arch_debug_save_registers(struct arch_debug_registers* registers) +arch_debug_save_registers(arch_debug_registers* registers) { // get the caller's frame pointer stack_frame* frame = (stack_frame*)x86_get_stack_frame(); @@ -978,14 +1020,14 @@ arch_debug_stack_trace(void) bool -arch_debug_contains_call(Thread *thread, const char *symbol, - addr_t start, addr_t end) +arch_debug_contains_call(Thread* thread, const char* symbol, addr_t start, + addr_t end) { DebuggedThreadSetter threadSetter(thread); - addr_t ebp; + addr_t bp; if (thread == thread_get_current_thread()) - ebp = x86_get_stack_frame(); + bp = x86_get_stack_frame(); else { if (thread->state == B_THREAD_RUNNING) { // The thread is currently running on another CPU. @@ -995,38 +1037,38 @@ arch_debug_contains_call(Thread *thread, const char *symbol, thread->cpu->cpu_num); if (registers == NULL) return false; - ebp = registers->bp; + bp = registers->bp; } else { // thread not running - ebp = thread->arch_info.current_stack.esp[2]; + bp = thread->arch_info.GetFramePointer(); } } for (;;) { - if (!is_kernel_stack_address(thread, ebp)) + if (!is_kernel_stack_address(thread, bp)) break; - if (is_iframe(thread, ebp)) { - struct iframe *frame = (struct iframe *)ebp; + if (is_iframe(thread, bp)) { + iframe* frame = (iframe*)bp; if (is_calling(thread, frame->ip, symbol, start, end)) return true; - ebp = frame->bp; + bp = frame->bp; } else { - addr_t eip, nextEbp; + addr_t ip, nextBp; - if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK - || eip == 0 || ebp == 0) + if (get_next_frame_no_debugger(bp, &nextBp, &ip) != B_OK + || ip == 0 || bp == 0) break; - if (is_calling(thread, eip, symbol, start, end)) + if (is_calling(thread, ip, symbol, start, end)) return true; - ebp = nextEbp; + bp = nextBp; } - if (ebp == 0) + if (bp == 0) break; } @@ -1034,11 +1076,11 @@ arch_debug_contains_call(Thread *thread, const char *symbol, } -void * +void* arch_debug_get_caller(void) { - struct stack_frame *frame = (struct stack_frame *)x86_get_stack_frame(); - return (void *)frame->previous->return_address; + stack_frame* frame = (stack_frame*)x86_get_stack_frame(); + return (void*)frame->previous->return_address; } @@ -1064,39 +1106,39 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, Thread* thread = thread_get_current_thread(); int32 count = 0; - addr_t ebp = x86_get_stack_frame(); + addr_t bp = x86_get_stack_frame(); bool onKernelStack = true; - while (ebp != 0 && count < maxCount) { + while (bp != 0 && count < maxCount) { onKernelStack = onKernelStack - && is_kernel_stack_address(thread, ebp); + && is_kernel_stack_address(thread, bp); if (!onKernelStack && (flags & STACK_TRACE_USER) == 0) break; - addr_t eip; - addr_t nextEbp; + addr_t ip; + addr_t nextBp; - if (onKernelStack && is_iframe(thread, ebp)) { - struct iframe *frame = (struct iframe*)ebp; - eip = frame->ip; - nextEbp = frame->bp; + if (onKernelStack && is_iframe(thread, bp)) { + iframe* frame = (iframe*)bp; + ip = frame->ip; + nextBp = frame->bp; if (skipIframes > 0) { if (--skipIframes == 0) skipFrames = 0; } } else { - if (get_next_frame_no_debugger(ebp, &nextEbp, &eip) != B_OK) + if (get_next_frame_no_debugger(bp, &nextBp, &ip) != B_OK) break; } if (skipFrames <= 0 && ((flags & STACK_TRACE_KERNEL) != 0 || onKernelStack)) { - returnAddresses[count++] = eip; + returnAddresses[count++] = ip; } else skipFrames--; - ebp = nextEbp; + bp = nextBp; } return count; @@ -1112,12 +1154,12 @@ arch_debug_get_stack_trace(addr_t* returnAddresses, int32 maxCount, void* arch_debug_get_interrupt_pc(bool* _isSyscall) { - struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); + iframe* frame = get_current_iframe(debug_get_debugged_thread()); if (frame == NULL) return NULL; if (_isSyscall != NULL) - *_isSyscall = frame->vector == 99; + *_isSyscall = frame->type == IFRAME_TYPE_SYSCALL; return (void*)(addr_t)frame->ip; } @@ -1129,7 +1171,14 @@ arch_debug_get_interrupt_pc(bool* _isSyscall) void arch_debug_unset_current_thread(void) { +#ifdef __x86_64__ + // Can't just write 0 to the GS base, that will cause the read from %gs:0 + // to fault. Instead point it at a NULL pointer, %gs:0 will get this value. + static Thread* unsetThread = NULL; + x86_write_msr(IA32_MSR_GS_BASE, (addr_t)&unsetThread); +#else x86_write_dr3(NULL); +#endif } @@ -1145,14 +1194,14 @@ status_t arch_set_debug_variable(const char* variableName, uint64 value) { bool settable; - uint32* variable = find_debug_variable(variableName, settable); + size_t* variable = find_debug_variable(variableName, settable); if (variable == NULL) return B_ENTRY_NOT_FOUND; if (!settable) return B_NOT_ALLOWED; - *variable = (uint32)value; + *variable = (size_t)value; return B_OK; } @@ -1161,7 +1210,7 @@ status_t arch_get_debug_variable(const char* variableName, uint64* value) { bool settable; - uint32* variable = find_debug_variable(variableName, settable); + size_t* variable = find_debug_variable(variableName, settable); if (variable == NULL) return B_ENTRY_NOT_FOUND; @@ -1170,6 +1219,12 @@ arch_get_debug_variable(const char* variableName, uint64* value) } +struct gdb_register { + int32 type; + int64 value; +}; + + /*! Writes the contents of the CPU registers at some fixed outer stack frame or iframe into the given buffer in the format expected by gdb. @@ -1183,10 +1238,36 @@ arch_get_debug_variable(const char* variableName, uint64* value) ssize_t arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) { - struct iframe* frame = get_current_iframe(debug_get_debugged_thread()); + iframe* frame = get_current_iframe(debug_get_debugged_thread()); if (frame == NULL) return B_NOT_SUPPORTED; +#ifdef __x86_64__ + // For x86_64 the register order is: + // + // rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, + // r8, r9, r10, r11, r12, r13, r14, r15, + // rip, rflags, cs, ss, ds, es, fs, gs + // + // Annoyingly, GDB wants all the registers as 64-bit values, but then + // RFLAGS and the segment registers as 32-bit values, hence the need for + // the type information. + static const int32 kRegisterCount = 24; + gdb_register registers[kRegisterCount] = { + { B_UINT64_TYPE, frame->ax }, { B_UINT64_TYPE, frame->bx }, + { B_UINT64_TYPE, frame->cx }, { B_UINT64_TYPE, frame->dx }, + { B_UINT64_TYPE, frame->si }, { B_UINT64_TYPE, frame->di }, + { B_UINT64_TYPE, frame->bp }, { B_UINT64_TYPE, frame->sp }, + { B_UINT64_TYPE, frame->r8 }, { B_UINT64_TYPE, frame->r9 }, + { B_UINT64_TYPE, frame->r10 }, { B_UINT64_TYPE, frame->r11 }, + { B_UINT64_TYPE, frame->r12 }, { B_UINT64_TYPE, frame->r13 }, + { B_UINT64_TYPE, frame->r14 }, { B_UINT64_TYPE, frame->r15 }, + { B_UINT64_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags }, + { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ss }, + { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 }, + { B_UINT32_TYPE, 0 }, { B_UINT32_TYPE, 0 }, + }; +#else // For x86 the register order is: // // eax, ecx, edx, ebx, @@ -1195,23 +1276,36 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) // cs, ss, ds, es, fs, gs // // Note that even though the segment descriptors are actually 16 bits wide, - // gdb requires them as 32 bit integers. Note also that for some reason - // gdb wants the register dump in *big endian* format. + // gdb requires them as 32 bit integers. static const int32 kRegisterCount = 16; - uint32 registers[kRegisterCount] = { - frame->ax, frame->cx, frame->dx, frame->bx, - frame->sp, frame->bp, frame->si, frame->di, - frame->ip, frame->flags, - frame->cs, frame->ds, frame->ds, frame->es, + gdb_register registers[kRegisterCount] = { + { B_UINT32_TYPE, frame->ax }, { B_UINT32_TYPE, frame->cx }, + { B_UINT32_TYPE, frame->dx }, { B_UINT32_TYPE, frame->bx }, + { B_UINT32_TYPE, frame->sp }, { B_UINT32_TYPE, frame->bp }, + { B_UINT32_TYPE, frame->si }, { B_UINT32_TYPE, frame->di }, + { B_UINT32_TYPE, frame->ip }, { B_UINT32_TYPE, frame->flags }, + { B_UINT32_TYPE, frame->cs }, { B_UINT32_TYPE, frame->ds }, // assume ss == ds - frame->fs, frame->gs + { B_UINT32_TYPE, frame->ds }, { B_UINT32_TYPE, frame->es }, + { B_UINT32_TYPE, frame->fs }, { B_UINT32_TYPE, frame->gs }, }; +#endif const char* const bufferStart = buffer; for (int32 i = 0; i < kRegisterCount; i++) { - int result = snprintf(buffer, bufferSize, "%08" B_PRIx32, - B_HOST_TO_BENDIAN_INT32(registers[i])); + // For some reason gdb wants the register dump in *big endian* format. + int result = 0; + switch (registers[i].type) { + case B_UINT64_TYPE: + result = snprintf(buffer, bufferSize, "%016" B_PRIx64, + B_HOST_TO_BENDIAN_INT64(registers[i].value)); + break; + case B_UINT32_TYPE: + result = snprintf(buffer, bufferSize, "%08" B_PRIx32, + B_HOST_TO_BENDIAN_INT32((uint32)registers[i].value)); + break; + } if (result >= (int)bufferSize) return B_BUFFER_OVERFLOW; @@ -1224,7 +1318,7 @@ arch_debug_gdb_get_registers(char* buffer, size_t bufferSize) status_t -arch_debug_init(kernel_args *args) +arch_debug_init(kernel_args* args) { // at this stage, the debugger command system is alive @@ -1234,7 +1328,9 @@ arch_debug_init(kernel_args *args) "Stack crawl for current thread (or any other)"); add_debugger_command("iframe", &dump_iframes, "Dump iframes for the specified thread"); +#ifndef __x86_64__ add_debugger_command("call", &show_call, "Show call with arguments"); +#endif add_debugger_command_etc("in_context", &cmd_in_context, "Executes a command in the context of a given thread", " ...\n" diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index d0a1769a43..401f9d42dc 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -108,15 +108,9 @@ x86_get_thread_user_iframe(Thread *thread) if (thread->state == B_THREAD_RUNNING) return NULL; - // Read frame pointer from the thread's stack. -#ifdef __x86_64__ - addr_t bp = thread->arch_info.current_stack[1]; -#else - addr_t bp = thread->arch_info.current_stack.esp[2]; -#endif - // find the user iframe - struct iframe* frame = find_previous_iframe(thread, bp); + struct iframe* frame = find_previous_iframe(thread, + thread->arch_info.GetFramePointer()); while (frame != NULL) { if (IFRAME_IS_USER(frame)) @@ -136,7 +130,7 @@ x86_get_current_iframe(void) phys_addr_t -x86_next_page_directory(Thread *from, Thread *to) +x86_next_page_directory(Thread* from, Thread* to) { VMAddressSpace* toAddressSpace = to->team->address_space; if (from->team->address_space == toAddressSpace) { From b2cd72d8f3c4a3710fdbaf36802de3d6e74a4066 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 14 Jul 2012 09:23:48 +0100 Subject: [PATCH 104/273] Implemented arch_debug_call_with_fault_handler for x86_64. --- src/system/kernel/arch/x86/64/arch.S | 47 +++++++++++++++++++++++++ src/system/kernel/arch/x86/64/stubs.cpp | 10 ------ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 58b4bcb994..7ec20cb39a 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -260,3 +260,50 @@ FUNCTION(arch_cpu_user_strlcpy): movq $-1, %rax ret FUNCTION_END(arch_cpu_user_strlcpy) + + +/*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu, + jmp_buf jumpBuffer, void (*function)(void*), void* parameter) + + Called by debug_call_with_fault_handler() to do the dirty work of setting + the fault handler and calling the function. If the function causes a page + fault, the arch_debug_call_with_fault_handler() calls longjmp() with the + given \a jumpBuffer. Otherwise it returns normally. + + debug_call_with_fault_handler() has already saved the CPU's fault_handler + and fault_handler_stack_pointer and will reset them later, so + arch_debug_call_with_fault_handler() doesn't need to care about it. + + \param cpu The \c cpu_ent for the current CPU. + \param jumpBuffer Buffer to be used for longjmp(). + \param function The function to be called. + \param parameter The parameter to be passed to the function to be called. +*/ +FUNCTION(arch_debug_call_with_fault_handler): + push %rbp + movq %rsp, %rbp + + // Preserve the jump buffer address for the fault return. + push %rsi + + // Set fault handler address, and fault handler stack pointer address. We + // don't need to save the previous values, since that's done by the caller. + movq $.L_debug_call_fault_handler, CPU_ENT_fault_handler(%rdi) + movq %rbp, CPU_ENT_fault_handler_stack_pointer(%rdi) + + // Call the function. + movq %rcx, %rdi + call *%rdx + + // Regular return. + movq %rbp, %rsp + pop %rbp + ret + +.L_debug_call_fault_handler: + // Fault -- return via longjmp(jumpBuffer, 1) + movq %rbp, %rsp + movq -8(%rsp), %rdi + movq $1, %rsi + call longjmp +FUNCTION_END(arch_debug_call_with_fault_handler) diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index b8efb2ff25..292572cc25 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -51,16 +51,6 @@ arch_commpage_init_post_cpus(void) } -void -arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, - void (*function)(void*), void* parameter) -{ - // To be implemented in asm, not here. - - function(parameter); -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; From 0cbce9aa4732e96acd9d593cb86ca0847a61d051 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 19 Jul 2012 12:45:17 +0100 Subject: [PATCH 105/273] A few 64-bit fixes for ELF/module code. --- src/system/kernel/elf.cpp | 12 ++++++------ src/system/kernel/module.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index e4682fe561..822d81885e 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -709,7 +709,7 @@ static status_t elf_parse_dynamic_section(struct elf_image_info *image) { elf_dyn *d; - int32 neededOffset = -1; + ssize_t neededOffset = -1; TRACE(("top of elf_parse_dynamic_section\n")); @@ -1139,7 +1139,7 @@ unload_elf_image(struct elf_image_info *image) if (atomic_add(&image->ref_count, -1) > 1) return; - TRACE(("unload image %ld, %s\n", image->id, image->name)); + TRACE(("unload image %" B_PRId32 ", %s\n", image->id, image->name)); unregister_elf_image(image); delete_elf_image(image); @@ -1228,7 +1228,7 @@ load_elf_symbol_table(int fd, struct elf_image_info *image) goto error3; } - TRACE(("loaded debug %ld symbols\n", numSymbols)); + TRACE(("loaded %" B_PRId32 " debug symbols\n", numSymbols)); // insert tables into image image->debug_symbols = symbolTable; @@ -1904,9 +1904,9 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry) B_PAGE_SIZE); if (programHeaders[i].p_flags & PF_WRITE) { // rw/data segment - uint32 memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + size_t memUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_memsz; - uint32 fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + size_t fileUpperBound = (programHeaders[i].p_vaddr % B_PAGE_SIZE) + programHeaders[i].p_filesz; memUpperBound = ROUNDUP(memUpperBound, B_PAGE_SIZE); @@ -2151,7 +2151,7 @@ load_kernel_add_on(const char *path) char regionName[B_OS_NAME_LENGTH]; elf_region *region; - TRACE(("looking at program header %ld\n", i)); + TRACE(("looking at program header %" B_PRId32 "\n", i)); switch (programHeaders[i].p_type) { case PT_LOAD: diff --git a/src/system/kernel/module.cpp b/src/system/kernel/module.cpp index a2b5157cba..81039b84e3 100644 --- a/src/system/kernel/module.cpp +++ b/src/system/kernel/module.cpp @@ -1100,7 +1100,7 @@ register_preloaded_module_image(struct preloaded_image* image) int32 index = 0; TRACE(("register_preloaded_module_image(image = %p, name = \"%s\")\n", - image, image->name)); + image, image->name.Pointer())); image->is_module = false; From 385d69fc0177827257822eec1274f4286bc6600d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 19 Jul 2012 17:53:46 +0100 Subject: [PATCH 106/273] Made it possible to build kernel modules for x86_64. Added the necessary build flags for modules, and added a module (dpc) to the floppy image for x86_64 builds for testing purposes. The module gets loaded correctly and its code runs without issue. Only non-trivial addition is the different method for generating kernel.so, this is explained in the kernel Jamfile. --- build/jam/BuildSetup | 20 ++++++++----- build/jam/FloppyBootImage | 11 +++++-- build/jam/KernelRules | 20 ++++++++++++- configure | 3 ++ src/system/kernel/Jamfile | 62 +++++++++++++++++++++++---------------- 5 files changed, 79 insertions(+), 37 deletions(-) diff --git a/build/jam/BuildSetup b/build/jam/BuildSetup index 2903225513..49a6d358dc 100644 --- a/build/jam/BuildSetup +++ b/build/jam/BuildSetup @@ -356,6 +356,7 @@ if $(HAIKU_GCC_VERSION[1]) >= 4 { HAIKU_KERNEL_PIC_CCFLAGS = -fno-pic ; HAIKU_KERNEL_PIC_LINKFLAGS = ; +HAIKU_KERNEL_ADDON_LINKFLAGS = ; switch $(HAIKU_ARCH) { case ppc : @@ -389,13 +390,16 @@ switch $(HAIKU_ARCH) { case x86_64 : { # Kernel lives in the top 2GB of the address space, use kernel code - # model. Also disable the red zone, which cannot be used in kernel - # code due to interrupts. - HAIKU_KERNEL_CCFLAGS += -mcmodel=kernel -mno-red-zone - -fno-omit-frame-pointer ; - HAIKU_KERNEL_C++FLAGS += -mcmodel=kernel -mno-red-zone - -fno-omit-frame-pointer ; + # model. + HAIKU_KERNEL_PIC_CCFLAGS += -mcmodel=kernel ; + + # Disable the red zone, which cannot be used in kernel code due to + # interrupts, and always enable the frame pointer so stack traces are + # correct. + HAIKU_KERNEL_CCFLAGS += -mno-red-zone -fno-omit-frame-pointer ; + HAIKU_KERNEL_C++FLAGS += -mno-red-zone -fno-omit-frame-pointer ; HAIKU_KERNEL_PIC_LINKFLAGS += -z max-page-size=0x1000 ; + HAIKU_KERNEL_ADDON_LINKFLAGS += -z max-page-size=0x1000 ; # Bootloader is 32-bit. HAIKU_BOOT_LINKFLAGS += -m elf_i386_haiku ; @@ -984,7 +988,7 @@ if $(TARGET_PLATFORM) != haiku { local buildVars = ARCH CPU GCC_VERSION KERNEL_ARCH - AR CC C++ LD OBJCOPY RANLIB + AR CC C++ LD OBJCOPY RANLIB ELFEDIT INCLUDES_SEPARATOR LOCAL_INCLUDES_OPTION SYSTEM_INCLUDES_OPTION @@ -993,7 +997,7 @@ local buildVars = KERNEL_DEFINES KERNEL_CCFLAGS KERNEL_C++FLAGS - KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS + KERNEL_PIC_CCFLAGS KERNEL_PIC_LINKFLAGS KERNEL_ADDON_LINKFLAGS BOOT_CCFLAGS BOOT_C++FLAGS BOOT_LINKFLAGS WARNING_CCFLAGS WARNING_C++FLAGS diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index 1af9d5b7eb..2bfe08f6b0 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -52,7 +52,10 @@ SYSTEM_ADD_ONS_BUS_MANAGERS = $(X86_ONLY)acpi $(ATA_ONLY)ata config_manager dpc SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; -if $(TARGET_ARCH) != x86_64 { +if $(TARGET_ARCH) = x86_64 { + AddFilesToFloppyBootArchive system add-ons kernel bus_managers + : dpc ; +} else { # modules AddFilesToFloppyBootArchive system add-ons kernel bus_managers : $(SYSTEM_ADD_ONS_BUS_MANAGERS) ; @@ -121,7 +124,11 @@ if $(NET_BOOT) = 1 { } # boot module links -if $(TARGET_ARCH) != x86_64 { +if $(TARGET_ARCH) = x86_64 { + AddBootModuleSymlinksToFloppyBootArchive + dpc + ; +} else { AddBootModuleSymlinksToFloppyBootArchive $(SYSTEM_ADD_ONS_BUS_MANAGERS) $(PPC_ONLY)openpic diff --git a/build/jam/KernelRules b/build/jam/KernelRules index 25b2260bf1..091e100bd2 100644 --- a/build/jam/KernelRules +++ b/build/jam/KernelRules @@ -77,6 +77,24 @@ actions KernelLd bind VERSION_SCRIPT --version-script=$(VERSION_SCRIPT) } +rule KernelSo target : source +{ + # KernelSo : + + Depends $(target) : copyattr $(source) ; + + MakeLocateDebug $(1) ; + KernelSo1 $(target) : copyattr $(source) ; +} + +actions KernelSo1 +{ + $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) + + $(2[1]) --data $(2[2]) $(1) && + $(HAIKU_ELFEDIT) --output-type dyn $(1) +} + rule KernelAddon { # KernelAddon : : : ; @@ -117,7 +135,7 @@ rule KernelAddon # compile and link SetupKernel $(sources) : $(TARGET_KERNEL_PIC_FLAGS) : false ; local linkFlags = -nostdlib -Xlinker --no-undefined - -Xlinker -soname=\"$(target:G=)\" ; + -Xlinker -soname=\"$(target:G=)\" $(TARGET_KERNEL_ADDON_LINKFLAGS) ; LINKFLAGS on $(target) = [ on $(target) return $(LINKFLAGS) ] $(linkFlags) ; Main $(target) : $(sources) ; LinkAgainst $(target) : $(libs) $(kernel) ; diff --git a/configure b/configure index 2b0dd89760..160679c768 100755 --- a/configure +++ b/configure @@ -344,6 +344,7 @@ set_default_value HAIKU_CC gcc set_default_value HAIKU_LD ld set_default_value HAIKU_OBJCOPY objcopy set_default_value HAIKU_RANLIB ranlib +set_default_value HAIKU_ELFEDIT elfedit set_default_value HAIKU_YASM yasm set_default_value HAIKU_CPPFLAGS "" set_default_value HAIKU_CCFLAGS "" @@ -510,6 +511,7 @@ if [ -n "$crossToolsPrefix" ]; then get_build_tool_path LD ld get_build_tool_path OBJCOPY objcopy get_build_tool_path RANLIB ranlib + get_build_tool_path ELFEDIT elfedit fi # prepare gcc settings @@ -570,6 +572,7 @@ HAIKU_CC ?= ${HAIKU_CC} ; HAIKU_LD ?= ${HAIKU_LD} ; HAIKU_OBJCOPY ?= ${HAIKU_OBJCOPY} ; HAIKU_RANLIB ?= ${HAIKU_RANLIB} ; +HAIKU_ELFEDIT ?= ${HAIKU_ELFEDIT} ; HAIKU_YASM ?= ${HAIKU_YASM} ; HAIKU_CPPFLAGS ?= ${HAIKU_CPPFLAGS} ; HAIKU_CCFLAGS ?= ${HAIKU_CCFLAGS} ; diff --git a/src/system/kernel/Jamfile b/src/system/kernel/Jamfile index d40862b7e9..0937fbbf0a 100644 --- a/src/system/kernel/Jamfile +++ b/src/system/kernel/Jamfile @@ -134,37 +134,47 @@ KernelLd kernel_$(TARGET_ARCH) : : ; -KernelLd kernel.so : - kernel_cache.o - kernel_core.o - kernel_debug.o - kernel_device_manager.o - kernel_disk_device_manager.o - kernel_fs.o - kernel_messaging.o - kernel_posix.o - kernel_slab.o - kernel_util.o - kernel_vm.o +if $(HAIKU_ARCH) = x86_64 { + # Cannot relink everything as a shared object on x86_64 as shared library + # code is required to be position-independent. Instead create a copy of the + # executable kernel image and change the ELF header type to DYN. A bit of + # a hack, but avoids having to recompile a PIC copy of the kernel code. + # kernel.so is only used when linking modules to provide symbol information, + # this is sufficient for that purpose. + KernelSo kernel.so : kernel_$(TARGET_ARCH) ; +} else { + KernelLd kernel.so : + kernel_cache.o + kernel_core.o + kernel_debug.o + kernel_device_manager.o + kernel_disk_device_manager.o + kernel_fs.o + kernel_messaging.o + kernel_posix.o + kernel_slab.o + kernel_util.o + kernel_vm.o - kernel_arch_$(TARGET_KERNEL_ARCH).o - kernel_platform_$(TARGET_BOOT_PLATFORM).o + kernel_arch_$(TARGET_KERNEL_ARCH).o + kernel_platform_$(TARGET_BOOT_PLATFORM).o - linkhack.so + linkhack.so - # kernel libroot parts - kernel_os_main.o - kernel_os_arch_$(TARGET_ARCH).o - kernel_lib_posix.o - kernel_lib_posix_arch_$(TARGET_ARCH).o - kernel_misc.o + # kernel libroot parts + kernel_os_main.o + kernel_os_arch_$(TARGET_ARCH).o + kernel_lib_posix.o + kernel_lib_posix_arch_$(TARGET_ARCH).o + kernel_misc.o - $(HAIKU_STATIC_LIBSUPC++) + $(HAIKU_STATIC_LIBSUPC++) - : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/kernel.ld - : -Bdynamic -shared -export-dynamic -dynamic-linker /foo/bar - $(TARGET_KERNEL_PIC_LINKFLAGS) -; + : $(HAIKU_TOP)/src/system/ldscripts/$(TARGET_ARCH)/kernel.ld + : -Bdynamic -shared -export-dynamic -dynamic-linker /foo/bar + $(TARGET_KERNEL_PIC_LINKFLAGS) + ; +} NotFile kernel ; Depends kernel : kernel_$(TARGET_ARCH) ; From 2865db34c861fc7e72d1076885e671b5b2d0e7dc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 11:53:46 +0100 Subject: [PATCH 107/273] Compile msi.cpp for x86_64. Needed to link the PCI module, not enabling it yet though, I'm not sure whether everything needed for it is in place yet. --- src/system/kernel/arch/x86/Jamfile | 2 +- src/system/kernel/arch/x86/arch_int.cpp | 2 +- src/system/kernel/arch/x86/msi.cpp | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index e95aa43e90..6fa9cea98d 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -54,7 +54,6 @@ if $(TARGET_ARCH) = x86_64 { arch_user_debugger.cpp ioapic.cpp irq_routing_table.cpp - msi.cpp syscall.S x86_signals.cpp x86_signals_asm.S @@ -90,6 +89,7 @@ local archGenericSources = arch_vm.cpp arch_vm_translation_map.cpp apic.cpp + msi.cpp pic.cpp # paging diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 21dedb3a67..9d35513e0f 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -237,8 +237,8 @@ arch_int_init_io(kernel_args* args) // TODO x86_64 #ifndef __x86_64__ ioapic_init(args); - msi_init(); #endif + msi_init(); return B_OK; } diff --git a/src/system/kernel/arch/x86/msi.cpp b/src/system/kernel/arch/x86/msi.cpp index 67b24225cc..62bfb84482 100644 --- a/src/system/kernel/arch/x86/msi.cpp +++ b/src/system/kernel/arch/x86/msi.cpp @@ -17,6 +17,10 @@ static bool sMSISupported = false; void msi_init() { +#ifdef __x86_64__ + // TODO x86_64. + return; +#endif if (!apic_available()) { dprintf("disabling msi due to missing apic\n"); return; From 9d4e925cf02e98d5385b5253bce07683d378883d Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 11:56:15 +0100 Subject: [PATCH 108/273] Support x86_64 in config_manager. --- .../kernel/bus_managers/config_manager/Jamfile | 3 ++- .../bus_managers/config_manager/config_manager.c | 16 +++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/config_manager/Jamfile b/src/add-ons/kernel/bus_managers/config_manager/Jamfile index b0333cae66..e88370ef0b 100644 --- a/src/add-ons/kernel/bus_managers/config_manager/Jamfile +++ b/src/add-ons/kernel/bus_managers/config_manager/Jamfile @@ -7,4 +7,5 @@ KernelAddon config_manager : : config_manager_arch.a ; -SubInclude HAIKU_TOP src add-ons kernel bus_managers config_manager arch $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src add-ons kernel bus_managers config_manager arch + $(TARGET_KERNEL_ARCH) ; diff --git a/src/add-ons/kernel/bus_managers/config_manager/config_manager.c b/src/add-ons/kernel/bus_managers/config_manager/config_manager.c index 4f6ede94aa..ccb7a66261 100644 --- a/src/add-ons/kernel/bus_managers/config_manager/config_manager.c +++ b/src/add-ons/kernel/bus_managers/config_manager/config_manager.c @@ -29,7 +29,7 @@ static pci_module_info *gPCI = NULL; static status_t driver_get_next_device_info(bus_type bus, uint64 *cookie, struct device_info *info, uint32 size) { - FUNCTION("(bus = %d, cookie = %lld)\n", bus, *cookie); + FUNCTION("(bus = %d, cookie = %" B_PRId64 ")\n", bus, *cookie); return B_ENTRY_NOT_FOUND; } @@ -37,7 +37,7 @@ driver_get_next_device_info(bus_type bus, uint64 *cookie, struct device_info *in static status_t driver_get_device_info_for(uint64 id, struct device_info *info, uint32 size) { - FUNCTION("(id = %Ld)\n", id); + FUNCTION("(id = %" B_PRId64 ")\n", id); return B_ENTRY_NOT_FOUND; } @@ -45,7 +45,7 @@ driver_get_device_info_for(uint64 id, struct device_info *info, uint32 size) static status_t driver_get_size_of_current_configuration_for(uint64 id) { - FUNCTION("(id = %Ld)\n", id); + FUNCTION("(id = %" B_PRId64 ")\n", id); return B_ENTRY_NOT_FOUND; } @@ -53,7 +53,8 @@ driver_get_size_of_current_configuration_for(uint64 id) static status_t driver_get_current_configuration_for(uint64 id, struct device_configuration *current, uint32 size) { - FUNCTION("(id = %Ld, current = %p, size = %lu)\n", id, current, size); + FUNCTION("(id = %" B_PRId64 ", current = %p, size = %" B_PRIu32 ")\n", id, + current, size); return B_ENTRY_NOT_FOUND; } @@ -61,7 +62,7 @@ driver_get_current_configuration_for(uint64 id, struct device_configuration *cur static status_t driver_get_size_of_possible_configurations_for(uint64 id) { - FUNCTION("(id = %Ld)\n", id); + FUNCTION("(id = %" B_PRId64 ")\n", id); return B_ENTRY_NOT_FOUND; } @@ -69,7 +70,8 @@ driver_get_size_of_possible_configurations_for(uint64 id) static status_t driver_get_possible_configurations_for(uint64 id, struct possible_device_configurations *possible, uint32 size) { - FUNCTION("(id = %Ld, possible = %p, size = %lu)\n", id, possible, size); + FUNCTION("(id = %" B_PRId64 ", possible = %p, size = %" B_PRIu32 ")\n", id, + possible, size); return B_ENTRY_NOT_FOUND; } @@ -86,7 +88,7 @@ static status_t driver_get_nth_resource_descriptor_of_type(const struct device_configuration *config, uint32 num, resource_type type, resource_descriptor *descr, uint32 size) { - FUNCTION("(config = %p, num = %ld)\n", config, num); + FUNCTION("(config = %p, num = %" B_PRId32 ")\n", config, num); return B_ENTRY_NOT_FOUND; } From 12bd7812dd6b6eadb65789ca9fc2e270d7d66fd4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 12:00:20 +0100 Subject: [PATCH 109/273] Ported PCI module to x86_64. Uses the x86 architecture code, made fixes to printf formats and a couple of 64-bit fixes. Only potentially intrusive change is that I've changed PCI.h to use uint32 rather than ulong. I don't see any way this would cause any issues, though. --- build/jam/FloppyBootImage | 4 +- headers/os/drivers/PCI.h | 44 ++++++------- src/add-ons/kernel/bus_managers/pci/Jamfile | 5 +- .../bus_managers/pci/arch/x86/pci_msi.cpp | 2 +- src/add-ons/kernel/bus_managers/pci/pci.cpp | 49 +++++++++------ src/add-ons/kernel/bus_managers/pci/pci.h | 4 +- .../kernel/bus_managers/pci/pci_fixup.cpp | 22 +++---- .../kernel/bus_managers/pci/pci_info.cpp | 63 +++++++++++-------- .../kernel/bus_managers/pci/pci_module.cpp | 2 +- 9 files changed, 107 insertions(+), 88 deletions(-) diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index 2bfe08f6b0..b34dfdc0f0 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -54,7 +54,7 @@ SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; if $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system add-ons kernel bus_managers - : dpc ; + : config_manager dpc pci ; } else { # modules AddFilesToFloppyBootArchive system add-ons kernel bus_managers @@ -126,7 +126,7 @@ if $(NET_BOOT) = 1 { # boot module links if $(TARGET_ARCH) = x86_64 { AddBootModuleSymlinksToFloppyBootArchive - dpc + dpc config_manager pci ; } else { AddBootModuleSymlinksToFloppyBootArchive diff --git a/headers/os/drivers/PCI.h b/headers/os/drivers/PCI.h index 84535da8af..ef0b50653c 100644 --- a/headers/os/drivers/PCI.h +++ b/headers/os/drivers/PCI.h @@ -44,15 +44,15 @@ typedef struct pci_info { uchar reserved; /* filler, for alignment */ union { struct { - ulong cardbus_cis; /* CardBus CIS pointer */ + uint32 cardbus_cis; /* CardBus CIS pointer */ ushort subsystem_id; /* subsystem (add-in card) id */ ushort subsystem_vendor_id; /* subsystem (add-in card) vendor id */ - ulong rom_base; /* rom base address, viewed from host */ - ulong rom_base_pci; /* rom base addr, viewed from pci */ - ulong rom_size; /* rom size */ - ulong base_registers[6]; /* base registers, viewed from host */ - ulong base_registers_pci[6]; /* base registers, viewed from pci */ - ulong base_register_sizes[6]; /* size of what base regs point to */ + uint32 rom_base; /* rom base address, viewed from host */ + uint32 rom_base_pci; /* rom base addr, viewed from pci */ + uint32 rom_size; /* rom size */ + uint32 base_registers[6]; /* base registers, viewed from host */ + uint32 base_registers_pci[6]; /* base registers, viewed from pci */ + uint32 base_register_sizes[6]; /* size of what base regs point to */ uchar base_register_flags[6]; /* flags from base address fields */ uchar interrupt_line; /* interrupt line */ uchar interrupt_pin; /* interrupt pin */ @@ -60,9 +60,9 @@ typedef struct pci_info { uchar max_latency; /* how often PCI access needed */ } h0; struct { - ulong base_registers[2]; /* base registers, viewed from host */ - ulong base_registers_pci[2]; /* base registers, viewed from pci */ - ulong base_register_sizes[2]; /* size of what base regs point to */ + uint32 base_registers[2]; /* base registers, viewed from host */ + uint32 base_registers_pci[2]; /* base registers, viewed from pci */ + uint32 base_register_sizes[2]; /* size of what base regs point to */ uchar base_register_flags[2]; /* flags from base address fields */ uchar primary_bus; uchar secondary_bus; @@ -75,12 +75,12 @@ typedef struct pci_info { ushort memory_limit; ushort prefetchable_memory_base; ushort prefetchable_memory_limit; - ulong prefetchable_memory_base_upper32; - ulong prefetchable_memory_limit_upper32; + uint32 prefetchable_memory_base_upper32; + uint32 prefetchable_memory_limit_upper32; ushort io_base_upper16; ushort io_limit_upper16; - ulong rom_base; /* rom base address, viewed from host */ - ulong rom_base_pci; /* rom base addr, viewed from pci */ + uint32 rom_base; /* rom base address, viewed from host */ + uint32 rom_base_pci; /* rom base addr, viewed from pci */ uchar interrupt_line; /* interrupt line */ uchar interrupt_pin; /* interrupt pin */ ushort bridge_control; @@ -98,14 +98,14 @@ typedef struct pci_info { uchar subordinate_bus; uchar secondary_latency; ushort reserved; - ulong memory_base; - ulong memory_limit; - ulong memory_base_upper32; - ulong memory_limit_upper32; - ulong io_base; - ulong io_limit; - ulong io_base_upper32; - ulong io_limit_upper32; + uint32 memory_base; + uint32 memory_limit; + uint32 memory_base_upper32; + uint32 memory_limit_upper32; + uint32 io_base; + uint32 io_limit; + uint32 io_base_upper32; + uint32 io_limit_upper32; ushort secondary_status; ushort bridge_control; #endif /* __HAIKU_PCI_BUS_MANAGER_TESTING */ diff --git a/src/add-ons/kernel/bus_managers/pci/Jamfile b/src/add-ons/kernel/bus_managers/pci/Jamfile index 79d1b0e00a..c4ea478e92 100644 --- a/src/add-ons/kernel/bus_managers/pci/Jamfile +++ b/src/add-ons/kernel/bus_managers/pci/Jamfile @@ -3,7 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel bus_managers pci ; UsePrivateKernelHeaders ; UsePrivateHeaders shared ; UsePrivateHeaders [ FDirName kernel util ] ; -UseHeaders [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ; +UseHeaders [ FDirName $(SUBDIR) arch $(TARGET_KERNEL_ARCH) ] ; KernelAddon pci : pci.cpp @@ -20,4 +20,5 @@ ObjectHdrs [ FGristFiles pci_info$(SUFOBJ) ] : [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) apps devices ] ; Includes [ FGristFiles pci_info.cpp ] : pcihdr.h ; -SubInclude HAIKU_TOP src add-ons kernel bus_managers pci arch $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src add-ons kernel bus_managers pci arch + $(TARGET_KERNEL_ARCH) ; diff --git a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_msi.cpp b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_msi.cpp index 880c0c804c..719c490760 100644 --- a/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_msi.cpp +++ b/src/add-ons/kernel/bus_managers/pci/arch/x86/pci_msi.cpp @@ -163,7 +163,7 @@ pci_enable_msi(uint8 virtualBus, uint8 _device, uint8 function) gPCI->WriteConfig(device, info->capability_offset + PCI_msi_control, 2, info->control_value); - dprintf("msi enabled: 0x%04lx\n", + dprintf("msi enabled: 0x%04" B_PRIx32 "\n", gPCI->ReadConfig(device, info->capability_offset + PCI_msi_control, 2)); return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index 93bb755a06..c91ce3d149 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -350,7 +350,7 @@ display_io(int argc, char **argv) if (i != 0) kprintf("\n"); - kprintf("[0x%lx] ", address + i * itemSize); + kprintf("[0x%" B_PRIx32 "] ", address + i * itemSize); if (num > displayWidth) { // make sure the spacing in the last line is correct @@ -362,13 +362,13 @@ display_io(int argc, char **argv) switch (itemSize) { case 1: - kprintf(" %02x", pci_read_io_8(address + i * itemSize)); + kprintf(" %02" B_PRIx8, pci_read_io_8(address + i * itemSize)); break; case 2: - kprintf(" %04x", pci_read_io_16(address + i * itemSize)); + kprintf(" %04" B_PRIx16, pci_read_io_16(address + i * itemSize)); break; case 4: - kprintf(" %08lx", pci_read_io_32(address + i * itemSize)); + kprintf(" %08" B_PRIx32, pci_read_io_32(address + i * itemSize)); break; } } @@ -569,7 +569,7 @@ PCI::~PCI() status_t PCI::_CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus) { -#if defined(__INTEL__) +#if defined(__INTEL__) || defined(__x86_64__) // IA32 doesn't use domains if (domain) @@ -607,7 +607,7 @@ PCI::_CreateVirtualBus(int domain, uint8 bus, uint8 *virtualBus) status_t PCI::ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus) { -#if defined(__INTEL__) +#if defined(__INTEL__) || defined(__x86_64__) // IA32 doesn't use domains *bus = virtualBus; @@ -739,8 +739,11 @@ PCI::_EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus) if (baseClass != PCI_bridge || subClass != PCI_pci) continue; - TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", domain, bus, dev, function)); - TRACE(("PCI: original settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", + TRACE(("PCI: found PCI-PCI bridge: domain %u, bus %u, dev %u, func %u\n", + domain, bus, dev, function)); + TRACE(("PCI: original settings: pcicmd %04" B_PRIx32 ", primary-bus " + "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " + "%" B_PRIu32 "\n", ReadConfig(domain, bus, dev, function, PCI_command, 2), ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), @@ -758,7 +761,9 @@ PCI::_EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus) WriteConfig(domain, bus, dev, function, PCI_secondary_bus, 1, 0); WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, 0); - TRACE(("PCI: disabled settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", + TRACE(("PCI: disabled settings: pcicmd %04" B_PRIx32 ", primary-bus " + "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " + "%" B_PRIu32 "\n", ReadConfig(domain, bus, dev, function, PCI_command, 2), ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), @@ -803,7 +808,9 @@ PCI::_EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus) pcicmd |= PCI_command_io | PCI_command_memory | PCI_command_master; WriteConfig(domain, bus, dev, function, PCI_command, 2, pcicmd); - TRACE(("PCI: probing settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", + TRACE(("PCI: probing settings: pcicmd %04" B_PRIx32 ", primary-bus " + "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " + "%" B_PRIu32 "\n", ReadConfig(domain, bus, dev, function, PCI_command, 2), ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), @@ -815,7 +822,9 @@ PCI::_EnumerateBus(int domain, uint8 bus, uint8 *subordinateBus) // close Scheunentor WriteConfig(domain, bus, dev, function, PCI_subordinate_bus, 1, lastUsedBusNumber); - TRACE(("PCI: configured settings: pcicmd %04lx, primary-bus %lu, secondary-bus %lu, subordinate-bus %lu\n", + TRACE(("PCI: configured settings: pcicmd %04" B_PRIx32 ", primary-bus " + "%" B_PRIu32 ", secondary-bus %" B_PRIu32 ", subordinate-bus " + "%" B_PRIu32 "\n", ReadConfig(domain, bus, dev, function, PCI_command, 2), ReadConfig(domain, bus, dev, function, PCI_primary_bus, 1), ReadConfig(domain, bus, dev, function, PCI_secondary_bus, 1), @@ -1236,11 +1245,11 @@ PCI::_ReadHeaderInfo(PCIDev *dev) WriteConfig(dev->domain, dev->bus, dev->device, dev->function, PCI_command, 2, pcicmd); - dev->info.u.h0.rom_base = (ulong)pci_ram_address( - (void *)dev->info.u.h0.rom_base_pci); + dev->info.u.h0.rom_base = (addr_t)pci_ram_address( + (void *)(addr_t)dev->info.u.h0.rom_base_pci); for (int i = 0; i < 6; i++) { - dev->info.u.h0.base_registers[i] = (ulong)pci_ram_address( - (void *)dev->info.u.h0.base_registers_pci[i]); + dev->info.u.h0.base_registers[i] = (addr_t)pci_ram_address( + (void *)(addr_t)dev->info.u.h0.base_registers_pci[i]); } dev->info.u.h0.cardbus_cis = ReadConfig(dev->domain, dev->bus, @@ -1282,11 +1291,11 @@ PCI::_ReadHeaderInfo(PCIDev *dev) WriteConfig(dev->domain, dev->bus, dev->device, dev->function, PCI_command, 2, pcicmd); - dev->info.u.h1.rom_base = (ulong)pci_ram_address( - (void *)dev->info.u.h1.rom_base_pci); + dev->info.u.h1.rom_base = (addr_t)pci_ram_address( + (void *)(addr_t)dev->info.u.h1.rom_base_pci); for (int i = 0; i < 2; i++) { - dev->info.u.h1.base_registers[i] = (ulong)pci_ram_address( - (void *)dev->info.u.h1.base_registers_pci[i]); + dev->info.u.h1.base_registers[i] = (addr_t)pci_ram_address( + (void *)(addr_t)dev->info.u.h1.base_registers_pci[i]); } dev->info.u.h1.primary_bus = ReadConfig(dev->domain, dev->bus, @@ -1397,7 +1406,7 @@ PCI::_RefreshDeviceInfo(PCIBus *bus) for (PCIDev *dev = bus->child; dev; dev = dev->next) { _ReadBasicInfo(dev); _ReadHeaderInfo(dev); -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) pci_read_arch_info(dev); #endif if (dev->child) diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index 626ed79030..a75fcfed8e 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -15,7 +15,7 @@ #include "pci_controller.h" -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) #include "pci_arch_info.h" #endif @@ -47,7 +47,7 @@ struct PCIDev { uint8 device; uint8 function; pci_info info; -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) pci_arch_info arch_info; #endif }; diff --git a/src/add-ons/kernel/bus_managers/pci/pci_fixup.cpp b/src/add-ons/kernel/bus_managers/pci/pci_fixup.cpp index ac1365a6be..7ab20f61be 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_fixup.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_fixup.cpp @@ -44,7 +44,7 @@ jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, // Read controller control register (0x40). uint32 val = pci->ReadConfig(domain, bus, device, function, 0x40, 4); - dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08lx\n", val); + dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val); // Clear bits. val &= ~(1 << 1); @@ -67,7 +67,7 @@ jmicron_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, val |= (1 << 14); val |= (1 << 23); - dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08lx\n", val); + dprintf("jmicron_fixup_ahci: Register 0x40 : 0x%08" B_PRIx32 "\n", val); pci->WriteConfig(domain, bus, device, function, 0x40, 4, val); // Read IRQ from controller at function 0 and assign this IRQ to the @@ -108,9 +108,9 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, dprintf("intel_fixup_ahci: domain %u, bus %u, device %u, function %u, " "deviceId 0x%04x\n", domain, bus, device, function, deviceId); - dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", + dprintf("intel_fixup_ahci: 0x24: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); - dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", + dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x90, 1)); uint8 map = pci->ReadConfig(domain, bus, device, function, 0x90, 1); @@ -125,10 +125,10 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, pcicmd & ~(PCI_command_io | PCI_command_memory)); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff); - dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08lx\n", + dprintf("intel_fixup_ahci: ide-bar5 bits-1: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0); - dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08lx\n", + dprintf("intel_fixup_ahci: ide-bar5 bits-0: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); map &= ~0x03; @@ -136,10 +136,10 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, pci->WriteConfig(domain, bus, device, function, 0x90, 1, map); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0xffffffff); - dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08lx\n", + dprintf("intel_fixup_ahci: ahci-bar5 bits-1: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); pci->WriteConfig(domain, bus, device, function, 0x24, 4, 0); - dprintf("intel_fixup_ahci: ahci-bar5 bits-0: 0x%08lx\n", + dprintf("intel_fixup_ahci: ahci-bar5 bits-0: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); if (deviceId == 0x27c0 || deviceId == 0x27c4) // restore on ICH7 @@ -148,9 +148,9 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, pci->WriteConfig(domain, bus, device, function, PCI_command, 2, pcicmd); } - dprintf("intel_fixup_ahci: 0x24: 0x%08lx\n", + dprintf("intel_fixup_ahci: 0x24: 0x%08" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x24, 4)); - dprintf("intel_fixup_ahci: 0x90: 0x%02lx\n", + dprintf("intel_fixup_ahci: 0x90: 0x%02" B_PRIx32 "\n", pci->ReadConfig(domain, bus, device, function, 0x90, 1)); } @@ -158,7 +158,7 @@ intel_fixup_ahci(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, static void ati_fixup_ixp(PCI *pci, int domain, uint8 bus, uint8 device, uint8 function, uint16 deviceId) { -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) /* ATI Technologies Inc, IXP chipset: * This chipset seems broken, at least on my laptop I must force * the timer IRQ trigger mode, else no interrupt comes in. diff --git a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp index c869d92629..ba748a0fa8 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_info.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_info.cpp @@ -13,7 +13,7 @@ #include "pci.h" #define PCI_VERBOSE 1 -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) // enabling it makes the pci bus_manager binary about 1MB // some other platforms have issues with floppy image size... // TODO: Move this define to BuildSetup? @@ -42,11 +42,13 @@ print_pci2pci_bridge_info(const pci_info *info, bool verbose) uint32 io_limit = (((uint32)info->u.h1.io_limit & 0xf0) << 8) + 0xfff; if (info->u.h1.io_limit & 1) io_limit += info->u.h1.io_limit_upper16 << 16; - TRACE(("PCI: I/O window %04lx-%04lx\n", io_base, io_limit)); + TRACE(("PCI: I/O window %04" B_PRIx32 "-%04" B_PRIx32 "\n", io_base, + io_limit)); uint32 memory_base = ((uint32)info->u.h1.memory_base & 0xfff0) << 16; uint32 memory_limit = (((uint32)info->u.h1.memory_limit & 0xfff0) << 16) + 0xfffff; - TRACE(("PCI: memory window %04lx-%04lx\n", memory_base, memory_limit)); + TRACE(("PCI: memory window %04" B_PRIx32 "-%04" B_PRIx32 "\n", + memory_base, memory_limit)); uint64 prefetchable_memory_base = ((uint32)info->u.h1.prefetchable_memory_base & 0xfff0) << 16; if (info->u.h1.prefetchable_memory_base & 1) { @@ -60,18 +62,19 @@ print_pci2pci_bridge_info(const pci_info *info, bool verbose) prefetchable_memory_limit += (uint64)info->u.h1.prefetchable_memory_limit_upper32 << 32; } - TRACE(("PCI: prefetchable memory window %016llx-%016llx\n", + TRACE(("PCI: prefetchable memory window %016" B_PRIx64 "-%016" B_PRIx64 "\n", prefetchable_memory_base, prefetchable_memory_limit)); TRACE(("PCI: bridge_control %04x, secondary_status %04x\n", info->u.h1.bridge_control, info->u.h1.secondary_status)); TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x\n", info->u.h1.interrupt_line, info->u.h1.interrupt_pin)); - TRACE(("PCI: ROM base host %08lx, pci %08lx, size ??\n", + TRACE(("PCI: ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size ??\n", info->u.h1.rom_base, info->u.h1.rom_base_pci)); for (int i = 0; i < 2; i++) - TRACE(("PCI: base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n", - i, info->u.h1.base_registers[i], info->u.h1.base_registers_pci[i], - info->u.h1.base_register_sizes[i], info->u.h1.base_register_flags[i])); + TRACE(("PCI: base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", " + "size %08" B_PRIx32 ", flags %02x\n", i, info->u.h1.base_registers[i], + info->u.h1.base_registers_pci[i], info->u.h1.base_register_sizes[i], + info->u.h1.base_register_flags[i])); } @@ -79,18 +82,20 @@ static void print_pci2cardbus_bridge_info(const pci_info *info, bool verbose) { TRACE(("PCI: subsystem_id %04x, subsystem_vendor_id %04x\n", - info->u.h2.subsystem_id, info->u.h2.subsystem_vendor_id)); - TRACE(("PCI: primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, secondary_latency %02x\n", - info->u.h2.primary_bus, info->u.h2.secondary_bus, info->u.h2.subordinate_bus, info->u.h2.secondary_latency)); + info->u.h2.subsystem_id, info->u.h2.subsystem_vendor_id)); + TRACE(("PCI: primary_bus %02x, secondary_bus %02x, subordinate_bus %02x, " + "secondary_latency %02x\n", info->u.h2.primary_bus, + info->u.h2.secondary_bus, info->u.h2.subordinate_bus, + info->u.h2.secondary_latency)); TRACE(("PCI: bridge_control %04x, secondary_status %04x\n", - info->u.h2.bridge_control, info->u.h2.secondary_status)); - TRACE(("PCI: memory_base_upper32 %08lx, memory_base %08lx\n", - info->u.h2.memory_base_upper32, info->u.h2.memory_base)); - TRACE(("PCI: memory_limit_upper32 %08lx, memory_limit %08lx\n", - info->u.h2.memory_limit_upper32, info->u.h2.memory_limit)); - TRACE(("PCI: io_base_upper32 %08lx, io_base %08lx\n", + info->u.h2.bridge_control, info->u.h2.secondary_status)); + TRACE(("PCI: memory_base_upper32 %08" B_PRIx32 ", memory_base %08" + B_PRIx32 "\n", info->u.h2.memory_base_upper32, info->u.h2.memory_base)); + TRACE(("PCI: memory_limit_upper32 %08" B_PRIx32 ", memory_limit %08" + B_PRIx32 "\n", info->u.h2.memory_limit_upper32, info->u.h2.memory_limit)); + TRACE(("PCI: io_base_upper32 %08" B_PRIx32 ", io_base %08" B_PRIx32 "\n", info->u.h2.io_base_upper32, info->u.h2.io_base)); - TRACE(("PCI: io_limit_upper32 %08lx, io_limit %08lx\n", + TRACE(("PCI: io_limit_upper32 %08" B_PRIx32 ", io_limit %08" B_PRIx32 "\n", info->u.h2.io_limit_upper32, info->u.h2.io_limit)); } @@ -98,16 +103,20 @@ print_pci2cardbus_bridge_info(const pci_info *info, bool verbose) static void print_generic_info(const pci_info *info, bool verbose) { - TRACE(("PCI: ROM base host %08lx, pci %08lx, size %08lx\n", - info->u.h0.rom_base, info->u.h0.rom_base_pci, info->u.h0.rom_size)); - TRACE(("PCI: cardbus_CIS %08lx, subsystem_id %04x, subsystem_vendor_id %04x\n", - info->u.h0.cardbus_cis, info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id)); - TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x, min_grant %02x, max_latency %02x\n", - info->u.h0.interrupt_line, info->u.h0.interrupt_pin, info->u.h0.min_grant, info->u.h0.max_latency)); + TRACE(("PCI: ROM base host %08" B_PRIx32 ", pci %08" B_PRIx32 ", size " + "%08" B_PRIx32 "\n", info->u.h0.rom_base, info->u.h0.rom_base_pci, + info->u.h0.rom_size)); + TRACE(("PCI: cardbus_CIS %08" B_PRIx32 ", subsystem_id %04x, " + "subsystem_vendor_id %04x\n", info->u.h0.cardbus_cis, + info->u.h0.subsystem_id, info->u.h0.subsystem_vendor_id)); + TRACE(("PCI: interrupt_line %02x, interrupt_pin %02x, min_grant %02x, " + "max_latency %02x\n", info->u.h0.interrupt_line, info->u.h0.interrupt_pin, + info->u.h0.min_grant, info->u.h0.max_latency)); for (int i = 0; i < 6; i++) - TRACE(("PCI: base reg %d: host %08lx, pci %08lx, size %08lx, flags %02x\n", - i, info->u.h0.base_registers[i], info->u.h0.base_registers_pci[i], - info->u.h0.base_register_sizes[i], info->u.h0.base_register_flags[i])); + TRACE(("PCI: base reg %d: host %08" B_PRIx32 ", pci %08" B_PRIx32 ", " + "size %08" B_PRIx32 ", flags %02x\n", i, info->u.h0.base_registers[i], + info->u.h0.base_registers_pci[i], info->u.h0.base_register_sizes[i], + info->u.h0.base_register_flags[i])); } diff --git a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp index 8685fdbb38..fc71f6c2f8 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci_module.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci_module.cpp @@ -89,7 +89,7 @@ module_info *modules[] = { (module_info *)&gPCIRootModule, (module_info *)&gPCIDeviceModule, (module_info *)&gPCILegacyDriverModule, -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) // add platforms when they provide an arch specific module (module_info *)&gPCIArchModule, #endif From 1b41387b5f54acc9ad4e71fc377d98eb63fbac74 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 17:14:17 +0100 Subject: [PATCH 110/273] Added missing packed attributes on disk_identifier. --- headers/private/kernel/boot/disk_identifier.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/headers/private/kernel/boot/disk_identifier.h b/headers/private/kernel/boot/disk_identifier.h index 52f2cebf37..b1c64e93fe 100644 --- a/headers/private/kernel/boot/disk_identifier.h +++ b/headers/private/kernel/boot/disk_identifier.h @@ -34,41 +34,41 @@ typedef struct disk_identifier { union { struct { uint16 base_address; - } legacy; + } _PACKED legacy; struct { uint8 bus; uint8 slot; uint8 function; - } pci; + } _PACKED pci; } bus; union { struct { bool master; - } ata; + } _PACKED ata; struct { bool master; uint8 logical_unit; - } atapi; + } _PACKED atapi; struct { uint8 logical_unit; - } scsi; + } _PACKED scsi; struct { uint8 tbd; - } usb; + } _PACKED usb; struct { uint64 guid; - } firewire; + } _PACKED firewire; struct { uint64 wwd; - } fibre; + } _PACKED fibre; struct { off_t size; struct { off_t offset; uint32 sum; - } check_sums[NUM_DISK_CHECK_SUMS]; - } unknown; + } _PACKED check_sums[NUM_DISK_CHECK_SUMS]; + } _PACKED unknown; } device; -} disk_identifier; +} _PACKED disk_identifier; #endif /* KERNEL_BOOT_DISK_IDENTIFIER_H */ From d7ec2fa3bfda5ba1674e97528fba2f4cfec00144 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 17:37:37 +0100 Subject: [PATCH 111/273] A couple of format string fixes for tracing printfs. --- src/system/kernel/device_manager/device_manager.cpp | 2 +- src/system/kernel/fs/vfs_boot.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index 239ac4bb6e..ec71aa1294 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -1513,7 +1513,7 @@ device_node::_AddPath(Stack& stack, const char* basePath, if (status == B_OK) status = stack.Push(path); - TRACE((" add path: \"%s\", %ld\n", path->Path(), status)); + TRACE((" add path: \"%s\", %" B_PRId32 "\n", path->Path(), status)); if (status != B_OK) delete path; diff --git a/src/system/kernel/fs/vfs_boot.cpp b/src/system/kernel/fs/vfs_boot.cpp index 21b1b9e627..3361217a76 100644 --- a/src/system/kernel/fs/vfs_boot.cpp +++ b/src/system/kernel/fs/vfs_boot.cpp @@ -194,8 +194,8 @@ DiskBootMethod::IsBootDevice(KDiskDevice* device, bool strict) return false; } - TRACE(("boot device: bus %ld, device %ld\n", disk->bus_type, - disk->device_type)); + TRACE(("boot device: bus %" B_PRId32 ", device %" B_PRId32 "\n", + disk->bus_type, disk->device_type)); // Assume that CD boots only happen off removable media. if (fMethod == BOOT_METHOD_CD && !device->IsRemovable()) From 0063d2ba513ddb6bd54c329aa0d16c7e184862da Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 17:47:12 +0100 Subject: [PATCH 112/273] Various 64-bit fixes to SCSI and ATA bus managers/drivers. Mostly compilation fixes, as well as a few 64-bit safety fixes. I've briefly looked through everything for any obvious issues and fixed the ones I've found, and it seems like they're working properly, though there could be some more well hidden ones that I've missed. --- src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp | 4 ++-- src/add-ons/kernel/bus_managers/ata/ATADevice.cpp | 2 +- src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp | 2 +- src/add-ons/kernel/bus_managers/scsi/queuing.cpp | 7 ++++--- .../kernel/bus_managers/scsi/scatter_gather.cpp | 7 ++++--- src/add-ons/kernel/bus_managers/scsi/scsi_internal.h | 10 +++++----- src/add-ons/kernel/bus_managers/scsi/scsi_io.cpp | 4 ++-- .../kernel/bus_managers/scsi/virtual_memory.cpp | 4 ++-- .../kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp | 7 ++++--- .../kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp | 3 ++- src/add-ons/kernel/generic/ata_adapter/ata_adapter.cpp | 8 ++++---- src/add-ons/kernel/generic/scsi_periph/block.cpp | 3 ++- src/add-ons/kernel/generic/scsi_periph/device.cpp | 2 +- 13 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp index 969ed2b328..1aefcbc4eb 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp @@ -29,7 +29,7 @@ ATAChannel::ATAChannel(device_node *node) gDeviceManager->get_attr_uint32(node, ATA_CHANNEL_ID_ITEM, &fChannelID, true); - snprintf(fDebugContext, sizeof(fDebugContext), " %lu", fChannelID); + snprintf(fDebugContext, sizeof(fDebugContext), " %" B_PRIu32, fChannelID); if (fUseDMA) { void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS); @@ -879,7 +879,7 @@ ATAChannel::_FlushAndWait(bigtime_t waitTime) status_t ATAChannel::_ReadPIOBlock(ATARequest *request, size_t length) { - uint32 transferred = 0; + size_t transferred = 0; status_t result = _TransferPIOBlock(request, length, &transferred); request->CCB()->data_resid -= transferred; diff --git a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp index f055eb1d75..323b30fd8b 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp @@ -574,7 +574,7 @@ ATADevice::Configure() status_t ATADevice::Identify() { - snprintf(fDebugContext, sizeof(fDebugContext), "%s %lu-%u", + snprintf(fDebugContext, sizeof(fDebugContext), "%s %" B_PRIu32 "-%u", IsATAPI() ? "pi" : "", fChannel->ChannelID(), fIndex); ATARequest request(false); diff --git a/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp b/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp index 9da56a54f1..338a45f647 100644 --- a/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/dma_buffer.cpp @@ -51,7 +51,7 @@ is_sg_list_dma_safe(scsi_ccb *request) } // if there are no further restrictions - be happy - if (dma_boundary == ~0UL && alignment == 0 && max_sg_block_size == 0) + if (dma_boundary == ~(uint32)0 && alignment == 0 && max_sg_block_size == 0) return true; // argh - controller is a bit picky, so make sure he likes us diff --git a/src/add-ons/kernel/bus_managers/scsi/queuing.cpp b/src/add-ons/kernel/bus_managers/scsi/queuing.cpp index 3282b74f80..58d151622c 100644 --- a/src/add-ons/kernel/bus_managers/scsi/queuing.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/queuing.cpp @@ -55,7 +55,8 @@ static void scsi_insert_new_request( scsi_device_info *device, { scsi_ccb *first, *last, *before, *next; - SHOW_FLOW( 3, "inserting new_request=%p, pos=%Ld", new_request, new_request->sort ); + SHOW_FLOW( 3, "inserting new_request=%p, pos=%" B_PRId64, new_request, + new_request->sort ); first = device->queued_reqs; @@ -65,7 +66,7 @@ static void scsi_insert_new_request( scsi_device_info *device, return; } - SHOW_FLOW( 3, "first=%p, pos=%Ld, last_pos=%Ld", + SHOW_FLOW( 3, "first=%p, pos=%" B_PRId64 ", last_pos=%" B_PRId64, first, first->sort, device->last_sort ); // don't let syncs bypass others @@ -153,7 +154,7 @@ static void scsi_insert_new_request( scsi_device_info *device, return; } - SHOW_FLOW( 1, "inserting after %p (pos=%Ld) and before %p (pos=%Ld)", + SHOW_FLOW( 1, "inserting after %p (pos=%" B_PRId64 ") and before %p (pos=%" B_PRId64 ")", before, before->sort, next, next->sort ); // if we haven't found a proper position, we automatically insert diff --git a/src/add-ons/kernel/bus_managers/scsi/scatter_gather.cpp b/src/add-ons/kernel/bus_managers/scsi/scatter_gather.cpp index f4b2da0020..2d4977f430 100644 --- a/src/add-ons/kernel/bus_managers/scsi/scatter_gather.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/scatter_gather.cpp @@ -51,7 +51,7 @@ fill_temp_sg(scsi_ccb *ccb) if (mapped_len != ccb->data_length) goto too_complex; - if (dma_boundary != ~0UL || ccb->data_length > max_sg_block_size) { + if (dma_boundary != ~(uint32)0 || ccb->data_length > max_sg_block_size) { // S/G list may not be controller-compatible: // we have to split offending entries SHOW_FLOW(3, "Checking violation of dma boundary 0x%x and entry size 0x%x", @@ -64,7 +64,7 @@ fill_temp_sg(scsi_ccb *ccb) max_len = (dma_boundary + 1) - (temp_sg[cur_idx].address & dma_boundary); // restrict size per sg item - max_len = std::min(max_len, max_sg_block_size); + max_len = std::min(max_len, (addr_t)max_sg_block_size); SHOW_FLOW(4, "addr=%#" B_PRIxPHYSADDR ", size=%x, max_len=%x, " "idx=%d, num=%d", temp_sg[cur_idx].address, @@ -107,7 +107,8 @@ create_temp_sg(scsi_ccb *ccb) physical_entry *temp_sg; status_t res; - SHOW_FLOW(3, "ccb=%p, data=%p, data_length=%lu", ccb, ccb->data, ccb->data_length); + SHOW_FLOW(3, "ccb=%p, data=%p, data_length=%" B_PRIu32, ccb, ccb->data, + ccb->data_length); ccb->sg_list = temp_sg = (physical_entry*)locked_pool->alloc(temp_sg_pool); if (temp_sg == NULL) { diff --git a/src/add-ons/kernel/bus_managers/scsi/scsi_internal.h b/src/add-ons/kernel/bus_managers/scsi/scsi_internal.h index 5a1105ad32..1c4fd70635 100644 --- a/src/add-ons/kernel/bus_managers/scsi/scsi_internal.h +++ b/src/add-ons/kernel/bus_managers/scsi/scsi_internal.h @@ -121,21 +121,21 @@ typedef struct scsi_bus_info { typedef struct dma_buffer { area_id area; // area of DMA buffer uchar *address; // address of DMA buffer - uint32 size; // size of DMA buffer + size_t size; // size of DMA buffer area_id sg_list_area; // area of S/G list physical_entry *sg_list; // address of S/G list - uint32 sg_count; // number of entries in S/G list + size_t sg_count; // number of entries in S/G list bool inuse; // true, if in use bigtime_t last_use; // timestamp of last usage area_id sg_orig; // area of S/G list to original data physical_entry *sg_list_orig; // S/G list to original data - uint32 sg_count_max_orig; // maximum size (in entries) - uint32 sg_count_orig; // current size (in entries) + size_t sg_count_max_orig; // maximum size (in entries) + size_t sg_count_orig; // current size (in entries) uchar *orig_data; // pointer to original data const physical_entry *orig_sg_list; // original S/G list - uint32 orig_sg_count; // size of original S/G list + size_t orig_sg_count; // size of original S/G list } dma_buffer; diff --git a/src/add-ons/kernel/bus_managers/scsi/scsi_io.cpp b/src/add-ons/kernel/bus_managers/scsi/scsi_io.cpp index d07405a08d..23663d9cfc 100644 --- a/src/add-ons/kernel/bus_managers/scsi/scsi_io.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/scsi_io.cpp @@ -367,7 +367,7 @@ scsi_check_enqueue_request(scsi_ccb *request) if (request->sort >= 0) { device->last_sort = request->sort; - SHOW_FLOW(1, "%Ld", device->last_sort); + SHOW_FLOW(1, "%" B_PRId64, device->last_sort); } execute = true; @@ -618,7 +618,7 @@ scsi_check_exec_service(scsi_bus_info *bus) if (request->sort >= 0) { device->last_sort = request->sort; - SHOW_FLOW(1, "%Ld", device->last_sort); + SHOW_FLOW(1, "%" B_PRId64, device->last_sort); } RELEASE_BEN(&bus->mutex); diff --git a/src/add-ons/kernel/bus_managers/scsi/virtual_memory.cpp b/src/add-ons/kernel/bus_managers/scsi/virtual_memory.cpp index 94baaa832b..3dd7b8d129 100644 --- a/src/add-ons/kernel/bus_managers/scsi/virtual_memory.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/virtual_memory.cpp @@ -56,8 +56,8 @@ get_iovec_memory_map(iovec *vec, size_t vec_count, size_t vec_offset, size_t len range_start = (char *)vec->iov_base + vec_offset; range_len = std::min(vec->iov_len - vec_offset, left_len); - SHOW_FLOW( 3, "range_start=%x, range_len=%x", - (int)range_start, (int)range_len ); + SHOW_FLOW( 3, "range_start=%" B_PRIxADDR ", range_len=%" B_PRIxSIZE, + (addr_t)range_start, range_len ); vec_offset = 0; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp index e01fd5ef6e..69e7c67b74 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp @@ -184,8 +184,8 @@ test_capacity(cd_driver_info *info) } if (info->capacity != info->original_capacity) { - dprintf("scsi_cd: adjusted capacity from %llu to %llu blocks.\n", - info->original_capacity, info->capacity); + dprintf("scsi_cd: adjusted capacity from %" B_PRIu64 " to %" B_PRIu64 + " blocks.\n", info->original_capacity, info->capacity); } return B_OK; @@ -981,7 +981,8 @@ cd_set_capacity(cd_driver_info* info, uint64 capacity, uint32 blockSize) } if (info->block_size != 0) { - dprintf("old %ld, new %ld\n", info->block_size, blockSize); + dprintf("old %" B_PRId32 ", new %" B_PRId32 "\n", info->block_size, + blockSize); panic("updating DMAResource not yet implemented..."); } diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp index 0f2fe7f220..3075bd7655 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp @@ -417,7 +417,8 @@ das_set_capacity(das_driver_info* info, uint64 capacity, uint32 blockSize) if (info->block_size != blockSize) { if (info->block_size != 0) { - dprintf("old %ld, new %ld\n", info->block_size, blockSize); + dprintf("old %" B_PRId32 ", new %" B_PRId32 "\n", info->block_size, + blockSize); panic("updating DMAResource not yet implemented..."); } diff --git a/src/add-ons/kernel/generic/ata_adapter/ata_adapter.cpp b/src/add-ons/kernel/generic/ata_adapter/ata_adapter.cpp index 4289ed755b..e0a258a7b9 100644 --- a/src/add-ons/kernel/generic/ata_adapter/ata_adapter.cpp +++ b/src/add-ons/kernel/generic/ata_adapter/ata_adapter.cpp @@ -250,8 +250,8 @@ ata_adapter_prepare_dma(ata_adapter_channel_info *channel, writeToDevice ? "write" : "read", sgListCount); for (i = sgListCount - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sgList) { - prd->address = B_HOST_TO_LENDIAN_INT32((uint32)pci->ram_address(device, - (void*)(addr_t)sgList->address)); + prd->address = B_HOST_TO_LENDIAN_INT32((uint32)(addr_t)pci->ram_address( + device, (void*)(addr_t)sgList->address)); // 0 means 64K - this is done automatically be discarding upper 16 bits prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sgList->size); prd->EOT = i == 0; @@ -266,8 +266,8 @@ ata_adapter_prepare_dma(ata_adapter_channel_info *channel, pci->write_io_32(device, channel->bus_master_base + ATA_BM_PRDT_ADDRESS, (pci->read_io_32(device, channel->bus_master_base + ATA_BM_PRDT_ADDRESS) & 3) - | (B_HOST_TO_LENDIAN_INT32((uint32)pci->ram_address(device, - (void *)channel->prdt_phys)) & ~3)); + | (B_HOST_TO_LENDIAN_INT32((uint32)(addr_t)pci->ram_address(device, + (void*)(addr_t)channel->prdt_phys)) & ~3)); // reset interrupt and error signal status = pci->read_io_8(device, channel->bus_master_base diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp b/src/add-ons/kernel/generic/scsi_periph/block.cpp index 7ef69fb507..3b3ac63747 100644 --- a/src/add-ons/kernel/generic/scsi_periph/block.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp @@ -92,7 +92,8 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) blockSize = 0; } - SHOW_FLOW(3, "capacity = %lld, block_size = %ld", capacity, blockSize); + SHOW_FLOW(3, "capacity = %" B_PRId64 ", block_size = %" B_PRId32, capacity, + blockSize); device->block_size = blockSize; diff --git a/src/add-ons/kernel/generic/scsi_periph/device.cpp b/src/add-ons/kernel/generic/scsi_periph/device.cpp index d83a2ab1bf..5d8ab33055 100644 --- a/src/add-ons/kernel/generic/scsi_periph/device.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/device.cpp @@ -38,7 +38,7 @@ periph_compose_device_name(device_node *node, const char *prefix) // this is actually an IDE device, so we ignore the prefix // a bus device for those - snprintf(name, sizeof(name), "disk/ata%s/%ld/%s/raw", + snprintf(name, sizeof(name), "disk/ata%s/%" B_PRId32 "/%s/raw", type == scsi_dev_CDROM ? "pi" : "", channel, targetID == 0 ? "master" : "slave"); } else { From 7f7e76e4615a652686e68102907732d114968b58 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 17:53:59 +0100 Subject: [PATCH 113/273] 64-bit compilation fixes for write_overlay and intel partitioning system modules. --- .../layers/write_overlay/write_overlay.cpp | 4 +- .../intel/PartitionMapWriter.cpp | 21 +++++---- .../partitioning_systems/intel/intel.cpp | 28 ++++++----- .../intel/write_support.cpp | 47 +++++++++++-------- 4 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp index 5fd8d6c75c..cdd0916c0a 100644 --- a/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp +++ b/src/add-ons/kernel/file_systems/layers/write_overlay/write_overlay.cpp @@ -265,7 +265,7 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode, fIsDataModified(false), fFileCache(NULL) { - TRACE("inode created %lld\n", fInodeNumber); + TRACE("inode created %" B_PRIdINO "\n", fInodeNumber); recursive_lock_init(&fLock, "write overlay inode lock"); if (superVnode != NULL) @@ -290,7 +290,7 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode, OverlayInode::~OverlayInode() { - TRACE("inode destroyed %lld\n", fInodeNumber); + TRACE("inode destroyed %" B_PRIdINO "\n", fInodeNumber); if (fFileCache != NULL) file_cache_delete(fFileCache); diff --git a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp index 66cd6b7aa9..4f600e8836 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/PartitionMapWriter.cpp @@ -73,29 +73,30 @@ check_logical_location(const LogicalPartition* child, const PrimaryPartition* parent) { if (child->PartitionTableOffset() % child->BlockSize() != 0) { - TRACE(("check_logical_location() - PartitionTableOffset: %lld not a " - "multiple of media's block size: %ld\n", + TRACE(("check_logical_location() - PartitionTableOffset: %" B_PRId64 " " + "not a multiple of media's block size: %" B_PRId32 "\n", child->PartitionTableOffset(), child->BlockSize())); return false; } if (child->Offset() % child->BlockSize() != 0) { - TRACE(("check_logical_location() - Parition offset: %lld " - "is not a multiple of block size: %ld\n", child->Offset(), + TRACE(("check_logical_location() - Parition offset: %" B_PRId64 " " + "is not a multiple of block size: %" B_PRId32 "\n", child->Offset(), child->BlockSize())); return false; } if (child->Size() % child->BlockSize() != 0) { - TRACE(("check_logical_location() - Size: (%lld) is not a multiple of" - " block size: (%ld)\n", child->Size(), child->BlockSize())); + TRACE(("check_logical_location() - Size: (%" B_PRId64 ") is not a " + "multiple of block size: (%" B_PRId32 ")\n", child->Size(), + child->BlockSize())); return false; } if (child->PartitionTableOffset() < parent->Offset() || child->PartitionTableOffset() >= parent->Offset() + parent->Size()) { - TRACE(("check_logical_location() - Partition table: (%lld) not within " - "extended partition (start: %lld), (end: %lld)\n", - child->PartitionTableOffset(), parent->Offset(), parent->Offset() - + parent->Size())); + TRACE(("check_logical_location() - Partition table: (%" B_PRId64 ") not" + " within extended partition (start: %" B_PRId64 "), (end: " + "%" B_PRId64 ")\n", child->PartitionTableOffset(), parent->Offset(), + parent->Offset() + parent->Size())); return false; } if (child->Offset() + child->Size() > parent->Offset() + parent->Size()) { diff --git a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp index a1387d6d9c..bd8370b620 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/intel.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/intel.cpp @@ -99,7 +99,7 @@ get_type_for_content_type(const char* contentType, char* type) static status_t pm_std_ops(int32 op, ...) { - TRACE(("intel: pm_std_ops(0x%lx)\n", op)); + TRACE(("intel: pm_std_ops(0x%" B_PRIx32 ")\n", op)); switch(op) { case B_MODULE_INIT: case B_MODULE_UNINIT: @@ -117,9 +117,9 @@ pm_identify_partition(int fd, partition_data* partition, void** cookie) if (fd < 0 || !partition || !cookie) return -1; - TRACE(("intel: pm_identify_partition(%d, %ld: %lld, %lld, %ld)\n", fd, - partition->id, partition->offset, partition->size, - partition->block_size)); + TRACE(("intel: pm_identify_partition(%d, %" B_PRId32 ": %" B_PRId64 ", " + "%" B_PRId64 ", %" B_PRId32 ")\n", fd, partition->id, partition->offset, + partition->size, partition->block_size)); // reject extended partitions if (partition->type && !strcmp(partition->type, kPartitionTypeIntelExtended)) { @@ -182,9 +182,9 @@ pm_scan_partition(int fd, partition_data* partition, void* cookie) if (fd < 0 || !partition || !cookie) return B_ERROR; - TRACE(("intel: pm_scan_partition(%d, %ld: %lld, %lld, %ld)\n", fd, - partition->id, partition->offset, partition->size, - partition->block_size)); + TRACE(("intel: pm_scan_partition(%d, %" B_PRId32 ": %" B_PRId64 ", " + "%" B_PRId64 ", %" B_PRId32 ")\n", fd, partition->id, partition->offset, + partition->size, partition->block_size)); PartitionMapCookie* map = (PartitionMapCookie*)cookie; // fill in the partition_data structure @@ -287,7 +287,7 @@ pm_free_partition_content_cookie(partition_data* partition) static status_t ep_std_ops(int32 op, ...) { - TRACE(("intel: ep_std_ops(0x%lx)\n", op)); + TRACE(("intel: ep_std_ops(0x%" B_PRIx32 ")\n", op)); switch(op) { case B_MODULE_INIT: case B_MODULE_UNINIT: @@ -305,8 +305,9 @@ ep_identify_partition(int fd, partition_data* partition, void** cookie) if (fd < 0 || !partition || !cookie || !partition->cookie) return -1; - TRACE(("intel: ep_identify_partition(%d, %lld, %lld, %ld)\n", fd, - partition->offset, partition->size, partition->block_size)); + TRACE(("intel: ep_identify_partition(%d, %" B_PRId64 ", %" B_PRId64 ", " + "%" B_PRId32 ")\n", fd, partition->offset, partition->size, + partition->block_size)); // our parent must be a intel partition map partition and we must have // extended partition type @@ -333,8 +334,9 @@ ep_scan_partition(int fd, partition_data* partition, void* cookie) if (fd < 0 || !partition || !partition->cookie) return B_ERROR; - TRACE(("intel: ep_scan_partition(%d, %lld, %lld, %ld)\n", fd, - partition->offset, partition->size, partition->block_size)); + TRACE(("intel: ep_scan_partition(%d, %" B_PRId64 ", %" B_PRId64 ", " + "%" B_PRId32 ")\n", fd, partition->offset, partition->size, + partition->block_size)); partition_data* parent = get_parent_partition(partition->id); if (!parent) @@ -373,7 +375,7 @@ ep_scan_partition(int fd, partition_data* partition, void* cookie) // parameters char buffer[128]; - sprintf(buffer, "active %s ;\npartition_table_offset %lld ;\n", + sprintf(buffer, "active %s ;\npartition_table_offset %" B_PRId64 " ;\n", logical->Active() ? "true" : "false", logical->PartitionTableOffset()); child->parameters = strdup(buffer); diff --git a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp index a8ed002a83..b9d2bb0794 100644 --- a/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp +++ b/src/add-ons/kernel/partitioning_systems/intel/write_support.cpp @@ -679,7 +679,8 @@ get_partitionable_spaces(partition_data* partition, if (positions) delete[] positions; - TRACE(("intel: get_partitionable_spaces - found: %ld\n", actualCount)); + TRACE(("intel: get_partitionable_spaces - found: %" B_PRId32 "\n", + actualCount)); *_actualCount = actualCount; @@ -752,8 +753,8 @@ status_t pm_shadow_changed(partition_data* partition, partition_data* child, uint32 operation) { - TRACE(("intel: pm_shadow_changed(%p, %p, %lu)\n", partition, child, - operation)); + TRACE(("intel: pm_shadow_changed(%p, %p, %" B_PRIu32 ")\n", partition, + child, operation)); switch (operation) { case B_PARTITION_SHADOW: @@ -763,14 +764,16 @@ pm_shadow_changed(partition_data* partition, partition_data* child, partition->id); if (!physicalPartition) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW): no " - "physical partition with ID %ld\n", partition->id); + "physical partition with ID %" B_PRId32 "\n", + partition->id); return B_ERROR; } // clone the map if (!physicalPartition->content_cookie) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW): no " - "content cookie, physical partition: %ld\n", partition->id); + "content cookie, physical partition: %" B_PRId32 "\n", + partition->id); return B_ERROR; } @@ -796,13 +799,14 @@ pm_shadow_changed(partition_data* partition, partition_data* child, partition_data* physical = get_partition(child->id); if (!physical) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " - "no physical partition with ID %ld\n", child->id); + "no physical partition with ID %" B_PRId32 "\n", child->id); return B_ERROR; } if (!physical->cookie) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " - "no cookie, physical partition: %ld\n", child->id); + "no cookie, physical partition: %" B_PRId32 "\n", + child->id); return B_ERROR; } @@ -811,7 +815,7 @@ pm_shadow_changed(partition_data* partition, partition_data* child, if (!partition->content_cookie) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " - "no content cookie, physical partition: %ld\n", + "no content cookie, physical partition: %" B_PRId32 "\n", partition->id); return B_ERROR; } @@ -823,8 +827,8 @@ pm_shadow_changed(partition_data* partition, partition_data* child, if (!primary || primary->IsEmpty()) { dprintf("intel: pm_shadow_changed(B_PARTITION_SHADOW_CHILD): " - "partition %ld is empty, primary index: %ld\n", child->id, - index); + "partition %" B_PRId32 " is empty, primary index: " + "%" B_PRId32 "\n", child->id, index); return B_BAD_VALUE; } @@ -849,7 +853,8 @@ pm_shadow_changed(partition_data* partition, partition_data* child, { if (!partition->content_cookie) { dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " - "no content cookie, partition: %ld\n", partition->id); + "no content cookie, partition: %" B_PRId32 "\n", + partition->id); return B_ERROR; } @@ -867,7 +872,8 @@ pm_shadow_changed(partition_data* partition, partition_data* child, if (!primary) { dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " - "no empty primary slot, partition: %ld\n", partition->id); + "no empty primary slot, partition: %" B_PRId32 "\n", + partition->id); return B_ERROR; } @@ -876,7 +882,8 @@ pm_shadow_changed(partition_data* partition, partition_data* child, type.SetType(child->type); if (!type.IsValid()) { dprintf("intel: pm_shadow_changed(B_PARTITION_CREATE_CHILD): " - "invalid partition type, partition: %ld\n", partition->id); + "invalid partition type, partition: %" B_PRId32 "\n", + partition->id); return B_ERROR; } @@ -1065,7 +1072,7 @@ move_block(int fd, off_t fromOffset, off_t toOffset, uint8* buffer, int32 size) error = errno; if (error == B_OK) error = B_IO_ERROR; - TRACE(("intel: move_block(): reading failed: %lx\n", error)); + TRACE(("intel: move_block(): reading failed: %" B_PRIx32 "\n", error)); return error; } @@ -1074,7 +1081,7 @@ move_block(int fd, off_t fromOffset, off_t toOffset, uint8* buffer, int32 size) error = errno; if (error == B_OK) error = B_IO_ERROR; - TRACE(("intel: move_block(): writing failed: %lx\n", error)); + TRACE(("intel: move_block(): writing failed: %" B_PRIx32 "\n", error)); } return error; @@ -1520,9 +1527,9 @@ ep_is_sub_system_for(partition_data* partition) if (partition == NULL) return false; - TRACE(("intel: ep_is_sub_system_for(%ld: %lld, %lld, %ld, %s)\n", - partition->id, partition->offset, partition->size, - partition->block_size, partition->content_type)); + TRACE(("intel: ep_is_sub_system_for(%" B_PRId32 ": %" B_PRId64 ", " + "%" B_PRId64 ", %" B_PRId32 ", %s)\n", partition->id, partition->offset, + partition->size, partition->block_size, partition->content_type)); // Intel Extended Partition can live in child partition of Intel Partition // Map @@ -2280,8 +2287,8 @@ ep_delete_child(int fd, partition_id partitionID, partition_id childID, if (get_partition_from_offset_ep(partition, next->Offset(), &nextSibling)) { char buffer[128]; - sprintf(buffer, "active %s ;\npartition_table_offset %lld ;\n", - next->Active() ? "true" : "false", + sprintf(buffer, "active %s ;\npartition_table_offset %" B_PRId64 + " ;\n", next->Active() ? "true" : "false", next->PartitionTableOffset()); nextSibling->parameters = strdup(buffer); } From a9fdaec18aa39c5af3dd94a998325c520eb4423c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 20 Jul 2012 17:55:26 +0100 Subject: [PATCH 114/273] Added disk drivers and CD file system modules to the boot image for x86_64. This adds disk drivers, intel/session partitioning systems, and ISO9660 (+ write/attribute_overlay) modules to the CD/floppy boot image targets for x86_64. The kernel now detects and mounts the boot CD, and runs up to attempting to start the boot script. --- build/jam/FloppyBootImage | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index b34dfdc0f0..39a957be79 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -54,13 +54,32 @@ SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; if $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system add-ons kernel bus_managers - : config_manager dpc pci ; + : ata config_manager dpc pci scsi ; + AddFilesToFloppyBootArchive system add-ons kernel busses ata + : generic_ide_pci ; + AddFilesToFloppyBootArchive system add-ons kernel file_systems + : iso9660 attribute_overlay write_overlay ; + AddFilesToFloppyBootArchive system add-ons kernel generic + : ata_adapter locked_pool scsi_periph ; + AddFilesToFloppyBootArchive system add-ons kernel partitioning_systems + : intel session ; + + AddNewDriversToFloppyBootArchive disk scsi : scsi_cd scsi_disk ; } else { # modules AddFilesToFloppyBootArchive system add-ons kernel bus_managers : $(SYSTEM_ADD_ONS_BUS_MANAGERS) ; - AddFilesToFloppyBootArchive system add-ons kernel busses ide - : generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata it8211 ; + + if $(HAIKU_ATA_STACK) = 1 { + AddFilesToFloppyBootArchive system add-ons kernel busses ata + : generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata + it8211 ; + } else { + AddFilesToFloppyBootArchive system add-ons kernel busses ide + : generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata + it8211 ; + } + AddFilesToFloppyBootArchive system add-ons kernel busses scsi : ahci ; AddFilesToFloppyBootArchive system add-ons kernel console : vga_text ; @@ -126,7 +145,9 @@ if $(NET_BOOT) = 1 { # boot module links if $(TARGET_ARCH) = x86_64 { AddBootModuleSymlinksToFloppyBootArchive - dpc config_manager pci + ata dpc config_manager pci scsi ata_adapter locked_pool scsi_periph + generic_ide_pci scsi_cd scsi_disk intel session iso9660 + attribute_overlay write_overlay ; } else { AddBootModuleSymlinksToFloppyBootArchive From 4451c47c644320b88fe18a89993a2cf5b0d919b1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 21 Jul 2012 08:32:07 +0100 Subject: [PATCH 115/273] Compile generic_x86 CPU module for x86_64. --- build/jam/FloppyBootImage | 8 +++++--- src/add-ons/kernel/cpu/Jamfile | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index 39a957be79..458aa77cb9 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -3,7 +3,7 @@ local X86_ONLY = ; local PPC_ONLY = ; -if $(TARGET_ARCH) = x86 { +if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 { X86_ONLY = "" ; } else if $(TARGET_ARCH) = ppc { X86_ONLY = ; @@ -64,6 +64,8 @@ if $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system add-ons kernel partitioning_systems : intel session ; + AddFilesToFloppyBootArchive system add-ons kernel cpu : generic_x86 ; + AddNewDriversToFloppyBootArchive disk scsi : scsi_cd scsi_disk ; } else { # modules @@ -97,7 +99,7 @@ if $(TARGET_ARCH) = x86_64 { : uhci ohci ehci ; } - if $(TARGET_ARCH) = x86 { + if $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system add-ons kernel cpu : generic_x86 ; } @@ -146,7 +148,7 @@ if $(NET_BOOT) = 1 { if $(TARGET_ARCH) = x86_64 { AddBootModuleSymlinksToFloppyBootArchive ata dpc config_manager pci scsi ata_adapter locked_pool scsi_periph - generic_ide_pci scsi_cd scsi_disk intel session iso9660 + generic_x86 generic_ide_pci scsi_cd scsi_disk intel session iso9660 attribute_overlay write_overlay ; } else { diff --git a/src/add-ons/kernel/cpu/Jamfile b/src/add-ons/kernel/cpu/Jamfile index 8c8a5616e9..89decfdb70 100644 --- a/src/add-ons/kernel/cpu/Jamfile +++ b/src/add-ons/kernel/cpu/Jamfile @@ -1,3 +1,3 @@ SubDir HAIKU_TOP src add-ons kernel cpu ; -SubInclude HAIKU_TOP src add-ons kernel cpu $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src add-ons kernel cpu $(TARGET_KERNEL_ARCH) ; From 6497f6b1ec4dd21d85ec01a18098138b03986a98 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 21 Jul 2012 09:11:09 +0100 Subject: [PATCH 116/273] Moved the exception handling functions to arch_int.cpp, shared between x86 and x86_64. --- headers/private/kernel/arch/x86/arch_cpu.h | 10 +- headers/private/kernel/arch/x86/vm86.h | 4 + src/system/kernel/arch/x86/32/int.cpp | 215 +++------------------ src/system/kernel/arch/x86/64/int.cpp | 107 ++-------- src/system/kernel/arch/x86/arch_int.cpp | 168 +++++++++++++++- 5 files changed, 220 insertions(+), 284 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index a9100c77c5..836b27f7b1 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -407,7 +407,11 @@ bool x86_check_feature(uint32 feature, enum x86_feature_type type); void* x86_get_double_fault_stack(int32 cpu, size_t* _size); int32 x86_double_fault_get_cpu(void); -void x86_page_fault_exception(struct iframe* iframe); +void x86_invalid_exception(iframe* frame); +void x86_fatal_exception(iframe* frame); +void x86_unexpected_exception(iframe* frame); +void x86_hardware_interrupt(iframe* frame); +void x86_page_fault_exception(iframe* iframe); #ifndef __x86_64__ @@ -415,8 +419,8 @@ void x86_fnsave(void* fpuState); void x86_frstor(const void* fpuState); void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); void x86_set_task_gate(int32 cpu, int32 n, int32 segment); -void x86_double_fault_exception(struct iframe* frame); -void x86_page_fault_exception_double_fault(struct iframe* frame); +void x86_double_fault_exception(iframe* frame); +void x86_page_fault_exception_double_fault(iframe* frame); #endif diff --git a/headers/private/kernel/arch/x86/vm86.h b/headers/private/kernel/arch/x86/vm86.h index a7d939b422..7e4692da48 100644 --- a/headers/private/kernel/arch/x86/vm86.h +++ b/headers/private/kernel/arch/x86/vm86.h @@ -5,6 +5,9 @@ #ifndef _VM86_H #define _VM86_H + +#ifndef __x86_64__ + #include #include @@ -34,5 +37,6 @@ status_t vm86_do_int(struct vm86_state *state, uint8 vec); #endif #endif +#endif diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index b290c0df46..d718623538 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -9,14 +9,12 @@ * Distributed under the terms of the NewOS License. */ +#include + +#include #include -#include -#include -#include #include -#include -#include #include #include @@ -33,34 +31,6 @@ #include "interrupts.h" -#include - - -static const char *kInterruptNames[] = { - /* 0 */ "Divide Error Exception", - /* 1 */ "Debug Exception", - /* 2 */ "NMI Interrupt", - /* 3 */ "Breakpoint Exception", - /* 4 */ "Overflow Exception", - /* 5 */ "BOUND Range Exceeded Exception", - /* 6 */ "Invalid Opcode Exception", - /* 7 */ "Device Not Available Exception", - /* 8 */ "Double Fault Exception", - /* 9 */ "Coprocessor Segment Overrun", - /* 10 */ "Invalid TSS Exception", - /* 11 */ "Segment Not Present", - /* 12 */ "Stack Fault Exception", - /* 13 */ "General Protection Exception", - /* 14 */ "Page-Fault Exception", - /* 15 */ "-", - /* 16 */ "x87 FPU Floating-Point Error", - /* 17 */ "Alignment Check Exception", - /* 18 */ "Machine-Check Exception", - /* 19 */ "SIMD Floating-Point Exception", -}; -static const int kInterruptNameCount = 20; - -#define MAX_ARGS 16 static interrupt_descriptor* sIDTs[B_MAX_CPU_COUNT]; @@ -71,8 +41,6 @@ typedef void interrupt_handler_function(struct iframe* frame); interrupt_handler_function* gInterruptHandlerTable[ INTERRUPT_HANDLER_TABLE_SIZE]; -extern void hardware_interrupt(struct iframe* frame); - /*! Initializes a descriptor in an IDT. */ @@ -140,145 +108,6 @@ x86_get_idt(int32 cpu) // #pragma mark - -static const char * -exception_name(int number, char *buffer, int32 bufferSize) -{ - if (number >= 0 && number < kInterruptNameCount) - return kInterruptNames[number]; - - snprintf(buffer, bufferSize, "exception %d", number); - return buffer; -} - - -static void -invalid_exception(struct iframe* frame) -{ - Thread* thread = thread_get_current_thread(); - char name[32]; - panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %ld!\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, thread ? thread->id : -1); -} - - -static void -fatal_exception(struct iframe *frame) -{ - char name[32]; - panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), frame->error_code); -} - - -static void -unexpected_exception(struct iframe* frame) -{ - debug_exception_type type; - uint32 signalNumber; - int32 signalCode; - addr_t signalAddress = 0; - int32 signalError = B_ERROR; - - if (IFRAME_IS_VM86(frame)) { - x86_vm86_return((struct vm86_iframe *)frame, (frame->vector == 13) ? - B_OK : B_ERROR); - // won't get here - } - - switch (frame->vector) { - case 0: // Divide Error Exception (#DE) - type = B_DIVIDE_ERROR; - signalNumber = SIGFPE; - signalCode = FPE_INTDIV; - signalAddress = frame->ip; - break; - - case 4: // Overflow Exception (#OF) - type = B_OVERFLOW_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_INTOVF; - signalAddress = frame->ip; - break; - - case 5: // BOUND Range Exceeded Exception (#BR) - type = B_BOUNDS_CHECK_EXCEPTION; - signalNumber = SIGTRAP; - signalCode = SI_USER; - break; - - case 6: // Invalid Opcode Exception (#UD) - type = B_INVALID_OPCODE_EXCEPTION; - signalNumber = SIGILL; - signalCode = ILL_ILLOPC; - signalAddress = frame->ip; - break; - - case 13: // General Protection Exception (#GP) - type = B_GENERAL_PROTECTION_FAULT; - signalNumber = SIGILL; - signalCode = ILL_PRVOPC; // or ILL_PRVREG - signalAddress = frame->ip; - break; - - case 16: // x87 FPU Floating-Point Error (#MF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the FPU status - // register! - signalAddress = frame->ip; - break; - - case 17: // Alignment Check Exception (#AC) - type = B_ALIGNMENT_EXCEPTION; - signalNumber = SIGBUS; - signalCode = BUS_ADRALN; - // TODO: Also get the address (from where?). Since we don't enable - // alignment checking this exception should never happen, though. - signalError = EFAULT; - break; - - case 19: // SIMD Floating-Point Exception (#XF) - type = B_FLOATING_POINT_EXCEPTION; - signalNumber = SIGFPE; - signalCode = FPE_FLTDIV; - // TODO: Determine the correct cause via the MXCSR register! - signalAddress = frame->ip; - break; - - default: - invalid_exception(frame); - return; - } - - if (IFRAME_IS_USER(frame)) { - struct sigaction action; - Thread* thread = thread_get_current_thread(); - - enable_interrupts(); - - // If the thread has a signal handler for the signal, we simply send it - // the signal. Otherwise we notify the user debugger first. - if ((sigaction(signalNumber, NULL, &action) == 0 - && action.sa_handler != SIG_DFL - && action.sa_handler != SIG_IGN) - || user_debug_exception_occurred(type, signalNumber)) { - Signal signal(signalNumber, signalCode, signalError, - thread->team->id); - signal.SetAddress((void*)signalAddress); - send_signal_to_thread(thread, signal, 0); - } - } else { - char name[32]; - panic("Unexpected exception \"%s\" occurred in kernel mode! " - "Error code: 0x%lx\n", - exception_name(frame->vector, name, sizeof(name)), - frame->error_code); - } -} - - void x86_double_fault_exception(struct iframe* frame) { @@ -618,29 +447,29 @@ arch_int_init(struct kernel_args *args) // defaults for (i = 0; i < ARCH_INTERRUPT_BASE; i++) - table[i] = invalid_exception; + table[i] = x86_invalid_exception; for (i = ARCH_INTERRUPT_BASE; i < INTERRUPT_HANDLER_TABLE_SIZE; i++) - table[i] = hardware_interrupt; + table[i] = x86_hardware_interrupt; - table[0] = unexpected_exception; // Divide Error Exception (#DE) - table[1] = x86_handle_debug_exception; // Debug Exception (#DB) - table[2] = fatal_exception; // NMI Interrupt + table[0] = x86_unexpected_exception; // Divide Error Exception (#DE) + table[1] = x86_handle_debug_exception; // Debug Exception (#DB) + table[2] = x86_fatal_exception; // NMI Interrupt table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) - table[4] = unexpected_exception; // Overflow Exception (#OF) - table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) - table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) - table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) - table[9] = fatal_exception; // Coprocessor Segment Overrun - table[10] = fatal_exception; // Invalid TSS Exception (#TS) - table[11] = fatal_exception; // Segment Not Present (#NP) - table[12] = fatal_exception; // Stack Fault Exception (#SS) - table[13] = unexpected_exception; // General Protection Exception (#GP) + table[4] = x86_unexpected_exception; // Overflow Exception (#OF) + table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = x86_fatal_exception; // Device Not Available Exception (#NM) + table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) + table[9] = x86_fatal_exception; // Coprocessor Segment Overrun + table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS) + table[11] = x86_fatal_exception; // Segment Not Present (#NP) + table[12] = x86_fatal_exception; // Stack Fault Exception (#SS) + table[13] = x86_unexpected_exception; // General Protection Exception (#GP) table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) - table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) - table[17] = unexpected_exception; // Alignment Check Exception (#AC) - table[18] = fatal_exception; // Machine-Check Exception (#MC) - table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC) + table[18] = x86_fatal_exception; // Machine-Check Exception (#MC) + table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF) return B_OK; } diff --git a/src/system/kernel/arch/x86/64/int.cpp b/src/system/kernel/arch/x86/64/int.cpp index f0cfb800e6..1f43415abf 100644 --- a/src/system/kernel/arch/x86/64/int.cpp +++ b/src/system/kernel/arch/x86/64/int.cpp @@ -6,7 +6,6 @@ #include -#include #include #include @@ -22,78 +21,12 @@ typedef void interrupt_handler_function(iframe* frame); -static const char* kInterruptNames[] = { - /* 0 */ "Divide Error Exception", - /* 1 */ "Debug Exception", - /* 2 */ "NMI Interrupt", - /* 3 */ "Breakpoint Exception", - /* 4 */ "Overflow Exception", - /* 5 */ "BOUND Range Exceeded Exception", - /* 6 */ "Invalid Opcode Exception", - /* 7 */ "Device Not Available Exception", - /* 8 */ "Double Fault Exception", - /* 9 */ "Coprocessor Segment Overrun", - /* 10 */ "Invalid TSS Exception", - /* 11 */ "Segment Not Present", - /* 12 */ "Stack Fault Exception", - /* 13 */ "General Protection Exception", - /* 14 */ "Page-Fault Exception", - /* 15 */ "-", - /* 16 */ "x87 FPU Floating-Point Error", - /* 17 */ "Alignment Check Exception", - /* 18 */ "Machine-Check Exception", - /* 19 */ "SIMD Floating-Point Exception", -}; - static const uint32 kInterruptHandlerTableSize = 256; static interrupt_descriptor* sIDT; interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; extern uint8 isr_array[kInterruptHandlerTableSize][16]; -extern void hardware_interrupt(struct iframe* frame); - - -static const char* -exception_name(uint64 number, char* buffer, size_t bufferSize) -{ - if (number >= 0 - && number < (sizeof(kInterruptNames) / sizeof(kInterruptNames[0]))) - return kInterruptNames[number]; - - snprintf(buffer, bufferSize, "exception %lu", number); - return buffer; -} - - -static void -invalid_exception(iframe* frame) -{ - char name[32]; - panic("unhandled trap %#lx (%s) at ip %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip); -} - - -static void -fatal_exception(iframe* frame) -{ - char name[32]; - panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, frame->error_code); -} - - -static void -unexpected_exception(iframe* frame) -{ - char name[32]; - panic("fatal exception %#lx (%s) at ip %#lx, error code %#lx\n", - frame->vector, exception_name(frame->vector, name, sizeof(name)), - frame->ip, frame->error_code); -} /*! Returns the virtual IDT address for CPU \a cpu. */ @@ -134,31 +67,31 @@ arch_int_init(kernel_args* args) // Initialize the interrupt handler table. for (uint32 i = 0; i < ARCH_INTERRUPT_BASE; i++) - table[i] = invalid_exception; + table[i] = x86_invalid_exception; for (uint32 i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++) - table[i] = hardware_interrupt; + table[i] = x86_hardware_interrupt; - table[0] = unexpected_exception; // Divide Error Exception (#DE) + table[0] = x86_unexpected_exception; // Divide Error Exception (#DE) //table[1] = x86_handle_debug_exception; // Debug Exception (#DB) - table[1] = unexpected_exception; - table[2] = fatal_exception; // NMI Interrupt + table[1] = x86_unexpected_exception; + table[2] = x86_fatal_exception; // NMI Interrupt //table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) - table[3] = unexpected_exception; - table[4] = unexpected_exception; // Overflow Exception (#OF) - table[5] = unexpected_exception; // BOUND Range Exceeded Exception (#BR) - table[6] = unexpected_exception; // Invalid Opcode Exception (#UD) - table[7] = fatal_exception; // Device Not Available Exception (#NM) - table[8] = fatal_exception; // Double Fault Exception (#DF) - table[9] = fatal_exception; // Coprocessor Segment Overrun - table[10] = fatal_exception; // Invalid TSS Exception (#TS) - table[11] = fatal_exception; // Segment Not Present (#NP) - table[12] = fatal_exception; // Stack Fault Exception (#SS) - table[13] = unexpected_exception; // General Protection Exception (#GP) + table[3] = x86_unexpected_exception; + table[4] = x86_unexpected_exception; // Overflow Exception (#OF) + table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR) + table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD) + table[7] = x86_fatal_exception; // Device Not Available Exception (#NM) + table[8] = x86_fatal_exception; // Double Fault Exception (#DF) + table[9] = x86_fatal_exception; // Coprocessor Segment Overrun + table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS) + table[11] = x86_fatal_exception; // Segment Not Present (#NP) + table[12] = x86_fatal_exception; // Stack Fault Exception (#SS) + table[13] = x86_unexpected_exception; // General Protection Exception (#GP) table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) - table[16] = unexpected_exception; // x87 FPU Floating-Point Error (#MF) - table[17] = unexpected_exception; // Alignment Check Exception (#AC) - table[18] = fatal_exception; // Machine-Check Exception (#MC) - table[19] = unexpected_exception; // SIMD Floating-Point Exception (#XF) + table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF) + table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC) + table[18] = x86_fatal_exception; // Machine-Check Exception (#MC) + table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF) // Load the IDT. gdt_idt_descr idtr = { diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 9d35513e0f..f604defdb1 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -41,11 +42,176 @@ #endif +static const char *kInterruptNames[] = { + /* 0 */ "Divide Error Exception", + /* 1 */ "Debug Exception", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint Exception", + /* 4 */ "Overflow Exception", + /* 5 */ "BOUND Range Exceeded Exception", + /* 6 */ "Invalid Opcode Exception", + /* 7 */ "Device Not Available Exception", + /* 8 */ "Double Fault Exception", + /* 9 */ "Coprocessor Segment Overrun", + /* 10 */ "Invalid TSS Exception", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Fault Exception", + /* 13 */ "General Protection Exception", + /* 14 */ "Page-Fault Exception", + /* 15 */ "-", + /* 16 */ "x87 FPU Floating-Point Error", + /* 17 */ "Alignment Check Exception", + /* 18 */ "Machine-Check Exception", + /* 19 */ "SIMD Floating-Point Exception", +}; +static const int kInterruptNameCount = 20; + static const interrupt_controller* sCurrentPIC = NULL; +static const char* +exception_name(int number, char* buffer, int32 bufferSize) +{ + if (number >= 0 && number < kInterruptNameCount) + return kInterruptNames[number]; + + snprintf(buffer, bufferSize, "exception %d", number); + return buffer; +} + + void -hardware_interrupt(struct iframe* frame) +x86_invalid_exception(iframe* frame) +{ + Thread* thread = thread_get_current_thread(); + char name[32]; + panic("unhandled trap 0x%lx (%s) at ip 0x%lx, thread %" B_PRId32 "!\n", + frame->vector, exception_name(frame->vector, name, sizeof(name)), + frame->ip, thread ? thread->id : -1); +} + + +void +x86_fatal_exception(iframe* frame) +{ + char name[32]; + panic("Fatal exception \"%s\" occurred! Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), frame->error_code); +} + + +void +x86_unexpected_exception(iframe* frame) +{ + debug_exception_type type; + uint32 signalNumber; + int32 signalCode; + addr_t signalAddress = 0; + int32 signalError = B_ERROR; + +#ifndef __x86_64__ + if (IFRAME_IS_VM86(frame)) { + x86_vm86_return((vm86_iframe*)frame, (frame->vector == 13) ? + B_OK : B_ERROR); + // won't get here + } +#endif + + switch (frame->vector) { + case 0: // Divide Error Exception (#DE) + type = B_DIVIDE_ERROR; + signalNumber = SIGFPE; + signalCode = FPE_INTDIV; + signalAddress = frame->ip; + break; + + case 4: // Overflow Exception (#OF) + type = B_OVERFLOW_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_INTOVF; + signalAddress = frame->ip; + break; + + case 5: // BOUND Range Exceeded Exception (#BR) + type = B_BOUNDS_CHECK_EXCEPTION; + signalNumber = SIGTRAP; + signalCode = SI_USER; + break; + + case 6: // Invalid Opcode Exception (#UD) + type = B_INVALID_OPCODE_EXCEPTION; + signalNumber = SIGILL; + signalCode = ILL_ILLOPC; + signalAddress = frame->ip; + break; + + case 13: // General Protection Exception (#GP) + type = B_GENERAL_PROTECTION_FAULT; + signalNumber = SIGILL; + signalCode = ILL_PRVOPC; // or ILL_PRVREG + signalAddress = frame->ip; + break; + + case 16: // x87 FPU Floating-Point Error (#MF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the FPU status + // register! + signalAddress = frame->ip; + break; + + case 17: // Alignment Check Exception (#AC) + type = B_ALIGNMENT_EXCEPTION; + signalNumber = SIGBUS; + signalCode = BUS_ADRALN; + // TODO: Also get the address (from where?). Since we don't enable + // alignment checking this exception should never happen, though. + signalError = EFAULT; + break; + + case 19: // SIMD Floating-Point Exception (#XF) + type = B_FLOATING_POINT_EXCEPTION; + signalNumber = SIGFPE; + signalCode = FPE_FLTDIV; + // TODO: Determine the correct cause via the MXCSR register! + signalAddress = frame->ip; + break; + + default: + x86_invalid_exception(frame); + return; + } + + if (IFRAME_IS_USER(frame)) { + struct sigaction action; + Thread* thread = thread_get_current_thread(); + + enable_interrupts(); + + // If the thread has a signal handler for the signal, we simply send it + // the signal. Otherwise we notify the user debugger first. + if ((sigaction(signalNumber, NULL, &action) == 0 + && action.sa_handler != SIG_DFL + && action.sa_handler != SIG_IGN) + || user_debug_exception_occurred(type, signalNumber)) { + Signal signal(signalNumber, signalCode, signalError, + thread->team->id); + signal.SetAddress((void*)signalAddress); + send_signal_to_thread(thread, signal, 0); + } + } else { + char name[32]; + panic("Unexpected exception \"%s\" occurred in kernel mode! " + "Error code: 0x%lx\n", + exception_name(frame->vector, name, sizeof(name)), + frame->error_code); + } +} + + +void +x86_hardware_interrupt(struct iframe* frame) { int32 vector = frame->vector - ARCH_INTERRUPT_BASE; bool levelTriggered = false; From 5234e66d32184c0843e7c5020c23e28f88e50569 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 21 Jul 2012 11:55:13 +0100 Subject: [PATCH 117/273] Optimized memcpy/memset for x86_64. --- src/system/kernel/arch/x86/arch_cpu.cpp | 3 - src/system/kernel/lib/arch/x86_64/Jamfile | 11 ++- .../kernel/lib/arch/x86_64/arch_string.S | 96 +++++++++++++++++++ .../kernel/lib/arch/x86_64/arch_string.cpp | 36 ------- 4 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 src/system/kernel/lib/arch/x86_64/arch_string.S delete mode 100644 src/system/kernel/lib/arch/x86_64/arch_string.cpp diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 4fc23e4487..bcc9050cba 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -113,15 +113,12 @@ extern int memcpy_generic_end; extern "C" void memset_generic(void* dest, int value, size_t count); extern int memset_generic_end; -// TODO x86_64 -#ifndef __x86_64__ x86_optimized_functions gOptimizedFunctions = { memcpy_generic, &memcpy_generic_end, memset_generic, &memset_generic_end }; -#endif static status_t diff --git a/src/system/kernel/lib/arch/x86_64/Jamfile b/src/system/kernel/lib/arch/x86_64/Jamfile index 2e43cfd19a..66f5fb864f 100644 --- a/src/system/kernel/lib/arch/x86_64/Jamfile +++ b/src/system/kernel/lib/arch/x86_64/Jamfile @@ -1,5 +1,9 @@ SubDir HAIKU_TOP src system kernel lib arch x86_64 ; +# find the generated asm_offsets.h +SubDirHdrs [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) system kernel arch + $(TARGET_KERNEL_ARCH) ] ; + SEARCH_SOURCE += [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; local librootSources = [ FDirName $(HAIKU_TOP) src system libroot ] ; @@ -24,7 +28,12 @@ KernelMergeObject kernel_lib_posix_arch_$(TARGET_ARCH).o : kernel_longjmp_return.c kernel_setjmp_save_sigs.c - arch_string.cpp + arch_string.S : $(TARGET_KERNEL_PIC_CCFLAGS) ; + +# Explicitly tell the build system that arch_string.S includes the generated +# asm_offsets.h. +Includes [ FGristFiles arch_string.S ] + : asm_offsets.h ; diff --git a/src/system/kernel/lib/arch/x86_64/arch_string.S b/src/system/kernel/lib/arch/x86_64/arch_string.S new file mode 100644 index 0000000000..a24bbc8ff6 --- /dev/null +++ b/src/system/kernel/lib/arch/x86_64/arch_string.S @@ -0,0 +1,96 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include "asm_offsets.h" + + +.align 8 +FUNCTION(memcpy_generic): + push %rbp + movq %rsp, %rbp + + // Preserve original destination address for return value. + movq %rdi, %rax + + // size -> %rcx + movq %rdx, %rcx + + // For small copies, always do it bytewise, the additional overhead is + // not worth it. + cmp $24, %rcx + jl .Lmemcpy_generic_byte_copy + + // Do both source and dest have the same alignment? + movq %rsi, %r8 + xorq %rdi, %r8 + test $7, %r8 + jnz .Lmemcpy_generic_byte_copy + + // Align up to an 8-byte boundary. + movq %rdi, %r8 + andq $7, %r8 + jz .Lmemcpy_generic_qword_copy + movq $8, %rcx + subq %r8, %rcx + subq %rcx, %rdx // Subtract from the overall count. + rep + movsb + + // Get back the original count value. + movq %rdx, %rcx +.Lmemcpy_generic_qword_copy: + // Move by quadwords. + shrq $3, %rcx + rep + movsq + + // Get the remaining count. + movq %rdx, %rcx + andq $7, %rcx +.Lmemcpy_generic_byte_copy: + // Move any remaining data by bytes. + rep + movsb + + pop %rbp + ret +FUNCTION_END(memcpy_generic) +SYMBOL(memcpy_generic_end): + + +.align 8 +FUNCTION(memset_generic): + push %rbp + movq %rsp, %rbp + + // Preserve original destination address for return value. + movq %rdi, %r8 + + // size -> %rcx, value -> %al + movq %rdx, %rcx + movl %esi, %eax + + // Move by bytes. + rep + stosb + + movq %r8, %rax + pop %rbp + ret +FUNCTION_END(memset_generic) +SYMBOL(memset_generic_end): + + +FUNCTION(memcpy): + jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memcpy) +FUNCTION_END(memcpy) + +FUNCTION(memset): + jmp *(gOptimizedFunctions + X86_OPTIMIZED_FUNCTIONS_memset) +FUNCTION_END(memset) + diff --git a/src/system/kernel/lib/arch/x86_64/arch_string.cpp b/src/system/kernel/lib/arch/x86_64/arch_string.cpp deleted file mode 100644 index a3d6c8b8a4..0000000000 --- a/src/system/kernel/lib/arch/x86_64/arch_string.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. - * Distributed under the terms of the MIT License. -*/ - -// TODO: Replace these with optimized implementations. - - -#include - - -void * -memcpy(void *dest, const void *src, size_t count) -{ - const unsigned char *s = reinterpret_cast(src); - unsigned char *d = reinterpret_cast(dest); - - for (; count != 0; count--) { - *d++ = *s++; - } - - return dest; -} - - -void * -memset(void *dest, int val, size_t count) -{ - unsigned char *d = reinterpret_cast(dest); - - for (; count != 0; count--) { - *d++ = static_cast(val); - } - - return dest; -} From 195a0f350e3acd76856016f673c8a871ed687a07 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 21 Jul 2012 14:33:27 +0100 Subject: [PATCH 118/273] Changed argument type of fcntl syscall from uint32 to size_t. Since this argument may be used to pass pointers, uint32 is not correct for 64-bit. Effectively no change on 32-bit targets, both size_t and uint32 are unsigned long there. --- headers/private/kernel/vfs.h | 2 +- headers/private/system/syscalls.h | 2 +- src/system/kernel/fs/vfs.cpp | 12 +++++------- src/system/libroot/posix/fcntl.cpp | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index cdde48d47c..89d98b5801 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -176,7 +176,7 @@ int _user_open_dir_entry_ref(dev_t device, ino_t inode, const char *name); int _user_open_dir(int fd, const char *path); int _user_open_parent_dir(int fd, char *name, size_t nameLength); -status_t _user_fcntl(int fd, int op, uint32 argument); +status_t _user_fcntl(int fd, int op, size_t argument); status_t _user_fsync(int fd); status_t _user_flock(int fd, int op); status_t _user_read_stat(int fd, const char *path, bool traverseLink, diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 17f9b73d79..b104bb6cf8 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -253,7 +253,7 @@ extern int _kern_open_dir_entry_ref(dev_t device, ino_t inode, extern int _kern_open_dir(int fd, const char *path); extern int _kern_open_parent_dir(int fd, char *name, size_t nameLength); -extern status_t _kern_fcntl(int fd, int op, uint32 argument); +extern status_t _kern_fcntl(int fd, int op, size_t argument); extern status_t _kern_fsync(int fd); extern status_t _kern_flock(int fd, int op); extern off_t _kern_seek(int fd, off_t pos, int seekType); diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6e4dfd2d39..ace23089f2 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -5917,7 +5917,7 @@ common_ioctl(struct file_descriptor* descriptor, ulong op, void* buffer, static status_t -common_fcntl(int fd, int op, uint32 argument, bool kernel) +common_fcntl(int fd, int op, size_t argument, bool kernel) { struct flock flock; @@ -5934,10 +5934,9 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) status_t status = B_OK; if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) { - // TODO: x86_64 needs ulong argument here. if (descriptor->type != FDTYPE_FILE) status = B_BAD_VALUE; - else if (user_memcpy(&flock, (struct flock*)((ulong)argument), + else if (user_memcpy(&flock, (struct flock*)argument, sizeof(struct flock)) != B_OK) status = B_BAD_ADDRESS; @@ -6019,8 +6018,7 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel) status = get_advisory_lock(vnode, &flock); if (status == B_OK) { // copy back flock structure - // TODO: x86_64 - status = user_memcpy((struct flock*)((ulong)argument), &flock, + status = user_memcpy((struct flock*)argument, &flock, sizeof(struct flock)); } } else @@ -8087,7 +8085,7 @@ _kern_open_dir(int fd, const char* path) status_t -_kern_fcntl(int fd, int op, uint32 argument) +_kern_fcntl(int fd, int op, size_t argument) { return common_fcntl(fd, op, argument, true); } @@ -8901,7 +8899,7 @@ _user_open_parent_dir(int fd, char* userName, size_t nameLength) status_t -_user_fcntl(int fd, int op, uint32 argument) +_user_fcntl(int fd, int op, size_t argument) { status_t status = common_fcntl(fd, op, argument, false); if (op == F_SETLKW) diff --git a/src/system/libroot/posix/fcntl.cpp b/src/system/libroot/posix/fcntl.cpp index 2f99596145..1a82dec027 100644 --- a/src/system/libroot/posix/fcntl.cpp +++ b/src/system/libroot/posix/fcntl.cpp @@ -65,7 +65,7 @@ fcntl(int fd, int op, ...) { va_list args; va_start(args, op); - uint32 argument = va_arg(args, uint32); + size_t argument = va_arg(args, size_t); va_end(args); status_t error = _kern_fcntl(fd, op, argument); From 59ae45c1ab32476f1fa428dae22989f8387a1f9e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 21 Jul 2012 16:18:10 +0100 Subject: [PATCH 119/273] Fixed commpage for x86_64. Since the commpage is at a kernel address, changed 64-bit paging code to match x86's behaviour of allowing user-accessible mappings to be created in the kernel portion of the address space. This is also required by some drivers. --- .../private/system/arch/x86_64/arch_commpage_defs.h | 6 ++++-- src/system/boot/platform/bios_ia32/long.cpp | 2 +- src/system/kernel/arch/x86/arch_cpu.cpp | 4 +--- .../arch/x86/paging/64bit/X86PagingMethod64Bit.cpp | 12 +++++++----- src/system/kernel/commpage.cpp | 3 ++- src/system/kernel/elf.cpp | 2 +- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/headers/private/system/arch/x86_64/arch_commpage_defs.h b/headers/private/system/arch/x86_64/arch_commpage_defs.h index b2e2aff947..f298a32678 100644 --- a/headers/private/system/arch/x86_64/arch_commpage_defs.h +++ b/headers/private/system/arch/x86_64/arch_commpage_defs.h @@ -9,7 +9,9 @@ # error Must not be included directly. Include instead! #endif -// FIXME: correct address -#define ARCH_USER_COMMPAGE_ADDR (0xffff0000) +#define COMMPAGE_ENTRY_X86_MEMCPY (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0) +#define COMMPAGE_ENTRY_X86_MEMSET (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 1) + +#define ARCH_USER_COMMPAGE_ADDR (0xffffffffffff0000) #endif /* _SYSTEM_ARCH_x86_64_COMMPAGE_DEFS_H */ diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 3e50305afd..37e7b3701c 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -27,7 +27,7 @@ #include "mmu.h" -static const uint64 kTableMappingFlags = 0x3; +static const uint64 kTableMappingFlags = 0x7; static const uint64 kLargePageMappingFlags = 0x183; static const uint64 kPageMappingFlags = 0x103; // Global, R/W, Present diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index bcc9050cba..c5adaf70f1 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -922,8 +922,6 @@ arch_cpu_init_post_modules(kernel_args* args) call_all_cpus(&init_mtrrs, NULL); } - // TODO x86_64 -#ifndef __x86_64__ // get optimized functions from the CPU module if (sCpuModule != NULL && sCpuModule->get_optimized_functions != NULL) { x86_optimized_functions functions; @@ -960,7 +958,7 @@ arch_cpu_init_post_modules(kernel_args* args) elf_add_memory_image_symbol(image, "commpage_memset", ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_MEMSET], memsetLen, B_SYMBOL_TYPE_TEXT); -#endif + return B_OK; } diff --git a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp index a834cd264c..e9dbf30c4b 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86PagingMethod64Bit.cpp @@ -131,7 +131,8 @@ X86PagingMethod64Bit::MapEarly(kernel_args* args, addr_t virtualAddress, SetTableEntry(pdpte, (physicalPageDir & X86_64_PDPTE_ADDRESS_MASK) | X86_64_PDPTE_PRESENT - | X86_64_PDPTE_WRITABLE); + | X86_64_PDPTE_WRITABLE + | X86_64_PDPTE_USER); // Map it and zero it. virtualPageDir = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( @@ -154,7 +155,8 @@ X86PagingMethod64Bit::MapEarly(kernel_args* args, addr_t virtualAddress, SetTableEntry(pde, (physicalPageTable & X86_64_PDE_ADDRESS_MASK) | X86_64_PDE_PRESENT - | X86_64_PDE_WRITABLE); + | X86_64_PDE_WRITABLE + | X86_64_PDE_USER); // Map it and zero it. virtualPageTable = (uint64*)fKernelPhysicalPageMapper->GetPageTableAt( @@ -222,7 +224,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, SetTableEntry(pml4e, (physicalPDPT & X86_64_PML4E_ADDRESS_MASK) | X86_64_PML4E_PRESENT | X86_64_PML4E_WRITABLE - | (isKernel ? 0 : X86_64_PML4E_USER)); + | X86_64_PML4E_USER); mapCount++; } @@ -252,7 +254,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, SetTableEntry(pdpte, (physicalPageDir & X86_64_PDPTE_ADDRESS_MASK) | X86_64_PDPTE_PRESENT | X86_64_PDPTE_WRITABLE - | (isKernel ? 0 : X86_64_PDPTE_USER)); + | X86_64_PDPTE_USER); mapCount++; } @@ -282,7 +284,7 @@ X86PagingMethod64Bit::PageTableForAddress(uint64* virtualPML4, SetTableEntry(pde, (physicalPageTable & X86_64_PDE_ADDRESS_MASK) | X86_64_PDE_PRESENT | X86_64_PDE_WRITABLE - | (isKernel ? 0 : X86_64_PDE_USER)); + | X86_64_PDE_USER); mapCount++; } diff --git a/src/system/kernel/commpage.cpp b/src/system/kernel/commpage.cpp index aab641905a..4419bfd6cf 100644 --- a/src/system/kernel/commpage.cpp +++ b/src/system/kernel/commpage.cpp @@ -32,7 +32,8 @@ allocate_commpage_entry(int entry, size_t size) sFreeCommPageSpace = ALIGN_ENTRY((addr_t)sFreeCommPageSpace + size); sCommPageAddress[entry] = (addr_t)sUserCommPageAddress + ((addr_t)space - (addr_t)sCommPageAddress); -dprintf("allocate_commpage_entry(%d, %lu) -> %p\n", entry, size, (void*)sCommPageAddress[entry]); + dprintf("allocate_commpage_entry(%d, %lu) -> %p\n", entry, size, + (void*)sCommPageAddress[entry]); return space; } diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 822d81885e..8c639e5f3f 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -463,7 +463,7 @@ dump_symbols(int argc, char **argv) // dump symbols - kprintf("Symbols of image %" B_PRId32 "\"%s\":\n", image->id, image->name); + kprintf("Symbols of image %" B_PRId32 " \"%s\":\n", image->id, image->name); kprintf("%-*s Type Size Name\n", B_PRINTF_POINTER_WIDTH, "Address"); if (image->num_debug_symbols > 0) { From 1c24ebaa5fdc1d07cd40a296c59463c9477b8fbd Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 22 Jul 2012 10:42:35 +0100 Subject: [PATCH 120/273] 64-bit compilation fixes for BFS, add to x86_64 boot image. --- build/jam/FloppyBootImage | 6 ++--- .../kernel/file_systems/bfs/BPlusTree.cpp | 12 +++++----- .../file_systems/bfs/BlockAllocator.cpp | 20 ++++++++--------- src/add-ons/kernel/file_systems/bfs/Debug.cpp | 22 ++++++++++--------- .../kernel/file_systems/bfs/Journal.cpp | 20 ++++++++--------- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/build/jam/FloppyBootImage b/build/jam/FloppyBootImage index 458aa77cb9..1538fa7914 100644 --- a/build/jam/FloppyBootImage +++ b/build/jam/FloppyBootImage @@ -58,7 +58,7 @@ if $(TARGET_ARCH) = x86_64 { AddFilesToFloppyBootArchive system add-ons kernel busses ata : generic_ide_pci ; AddFilesToFloppyBootArchive system add-ons kernel file_systems - : iso9660 attribute_overlay write_overlay ; + : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; AddFilesToFloppyBootArchive system add-ons kernel generic : ata_adapter locked_pool scsi_periph ; AddFilesToFloppyBootArchive system add-ons kernel partitioning_systems @@ -148,8 +148,8 @@ if $(NET_BOOT) = 1 { if $(TARGET_ARCH) = x86_64 { AddBootModuleSymlinksToFloppyBootArchive ata dpc config_manager pci scsi ata_adapter locked_pool scsi_periph - generic_x86 generic_ide_pci scsi_cd scsi_disk intel session iso9660 - attribute_overlay write_overlay + generic_x86 generic_ide_pci scsi_cd scsi_disk intel session + $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; } else { AddBootModuleSymlinksToFloppyBootArchive diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp index 51b896a17b..5060525447 100644 --- a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp @@ -767,7 +767,7 @@ BPlusTree::Validate(bool repair, bool& _errorsFound) fHeader.MaxNumberOfLevels()); } - if (check.VisitedCount() != fHeader.MaximumSize() / fNodeSize) { + if ((off_t)check.VisitedCount() != fHeader.MaximumSize() / fNodeSize) { dprintf("inode %" B_PRIdOFF ": visited %" B_PRIuSIZE " from %" B_PRIdOFF " nodes.\n", fStream->ID(), check.VisitedCount(), fHeader.MaximumSize() / fNodeSize); @@ -791,7 +791,7 @@ BPlusTree::MakeEmpty() header->max_number_of_levels = HOST_ENDIAN_TO_BFS_INT32(1); header->root_node_pointer = HOST_ENDIAN_TO_BFS_INT64(NodeSize()); - if (fStream->Size() > NodeSize() * 2) + if (fStream->Size() > (off_t)NodeSize() * 2) header->free_node_pointer = HOST_ENDIAN_TO_BFS_INT64(2 * NodeSize()); else { header->free_node_pointer @@ -812,10 +812,10 @@ BPlusTree::MakeEmpty() offset += NodeSize()) { bplustree_node* node = cached.SetToWritable(transaction, offset, false); if (node == NULL) { - dprintf("--> could not open %lld\n", offset); + dprintf("--> could not open %" B_PRIdOFF "\n", offset); return B_IO_ERROR; } - if (offset < fStream->Size() - NodeSize()) + if (offset < fStream->Size() - (off_t)NodeSize()) node->left_link = HOST_ENDIAN_TO_BFS_INT64(offset + NodeSize()); else node->left_link = HOST_ENDIAN_TO_BFS_INT64((uint64)BPLUSTREE_NULL); @@ -2910,8 +2910,8 @@ bplustree_node::CheckIntegrity(uint32 nodeSize) const return B_BAD_DATA; } if (Values()[i] == -1) { - dprintf("invalid node %p, value %d: %lld: values corrupted\n", - this, (int)i, Values()[i]); + dprintf("invalid node %p, value %d: %" B_PRIdOFF ": values " + "corrupted\n", this, (int)i, Values()[i]); return B_BAD_DATA; } } diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index b0d446f75b..e49b3b3910 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -2131,8 +2131,8 @@ BlockAllocator::_AddInodeToIndex(Inode* inode) void BlockAllocator::Dump(int32 index) { - kprintf("allocation groups: %ld (base %p)\n", fNumGroups, fGroups); - kprintf("blocks per group: %ld\n", fBlocksPerGroup); + kprintf("allocation groups: %" B_PRId32 " (base %p)\n", fNumGroups, fGroups); + kprintf("blocks per group: %" B_PRId32 "\n", fBlocksPerGroup); for (int32 i = 0; i < fNumGroups; i++) { if (index != -1 && i != index) @@ -2140,15 +2140,15 @@ BlockAllocator::Dump(int32 index) AllocationGroup& group = fGroups[i]; - kprintf("[%3ld] num bits: %lu (%p)\n", i, group.NumBits(), - &group); - kprintf(" num blocks: %lu\n", group.NumBlocks()); - kprintf(" start: %ld\n", group.Start()); - kprintf(" first free: %ld\n", group.fFirstFree); - kprintf(" largest start: %ld%s\n", group.fLargestStart, + kprintf("[%3" B_PRId32 "] num bits: %" B_PRIu32 " (%p)\n", i, + group.NumBits(), &group); + kprintf(" num blocks: %" B_PRIu32 "\n", group.NumBlocks()); + kprintf(" start: %" B_PRId32 "\n", group.Start()); + kprintf(" first free: %" B_PRId32 "\n", group.fFirstFree); + kprintf(" largest start: %" B_PRId32 "%s\n", group.fLargestStart, group.fLargestValid ? "" : " (invalid)"); - kprintf(" largest length: %ld\n", group.fLargestLength); - kprintf(" free bits: %ld\n", group.fFreeBits); + kprintf(" largest length: %" B_PRId32 "\n", group.fLargestLength); + kprintf(" free bits: %" B_PRId32 "\n", group.fFreeBits); } } diff --git a/src/add-ons/kernel/file_systems/bfs/Debug.cpp b/src/add-ons/kernel/file_systems/bfs/Debug.cpp index f9c6cf71b8..02a8a58972 100644 --- a/src/add-ons/kernel/file_systems/bfs/Debug.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Debug.cpp @@ -299,8 +299,9 @@ dump_inode(int argc, char** argv) kprintf(" tree: %p\n", inode->Tree()); kprintf(" file cache: %p\n", inode->FileCache()); kprintf(" file map: %p\n", inode->Map()); - kprintf(" old size: %Ld\n", inode->OldSize()); - kprintf(" old last modified: %Ld\n", inode->OldLastModified()); + kprintf(" old size: %" B_PRIdOFF "\n", inode->OldSize()); + kprintf(" old last modified: %" B_PRIdOFF "\n", + inode->OldLastModified()); node = &inode->Node(); } @@ -334,8 +335,9 @@ dump_volume(int argc, char** argv) run.start = HOST_ENDIAN_TO_BFS_INT16(strtoul(arg + 1, NULL, 0)); run.length = 0; - kprintf("%ld.%u -> block %Ld, bitmap block %ld\n", - run.AllocationGroup(), run.Start(), volume->ToBlock(run), + kprintf("%" B_PRId32 ".%u -> block %" B_PRIdOFF ", bitmap block" + " %" B_PRId32 "\n", run.AllocationGroup(), run.Start(), + volume->ToBlock(run), volume->SuperBlock().BlocksPerAllocationGroup() * run.AllocationGroup() + 1); } else { @@ -343,16 +345,16 @@ dump_volume(int argc, char** argv) off_t offset = parse_expression(arg); block_run run = volume->ToBlockRun(offset); - kprintf("block %Ld -> %ld.%u, bitmap block %ld\n", offset, - run.AllocationGroup(), run.Start(), - volume->SuperBlock().BlocksPerAllocationGroup() + kprintf("block %" B_PRIdOFF " -> %" B_PRId32 ".%u, bitmap block" + " %" B_PRId32 "\n", offset, run.AllocationGroup(), + run.Start(), volume->SuperBlock().BlocksPerAllocationGroup() * run.AllocationGroup() + 1); } } return 0; } - kprintf("id: %ld\n", volume->ID()); + kprintf("id: %" B_PRId32 "\n", volume->ID()); kprintf("block cache: %p\n", volume->BlockCache()); kprintf("journal: %p\n", volume->GetJournal(0)); kprintf("allocator: %p\n", &volume->Allocator()); @@ -397,9 +399,9 @@ dump_block_run_array(int argc, char** argv) for (uint32 i = 0; i < count; i++) { if (blockSize != 0) - dprintf("[%3lu] %10" B_PRIdOFF " ", i, offset); + dprintf("[%3" B_PRIu32 "] %10" B_PRIdOFF " ", i, offset); else - dprintf("[%3lu] ", i); + dprintf("[%3" B_PRIu32 "] ", i); uint32 size = runs[i].Length() * blockSize; if (searchOffset != 0 && searchOffset >= offset diff --git a/src/add-ons/kernel/file_systems/bfs/Journal.cpp b/src/add-ons/kernel/file_systems/bfs/Journal.cpp index f1a1f74a2a..593972e515 100644 --- a/src/add-ons/kernel/file_systems/bfs/Journal.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Journal.cpp @@ -1083,15 +1083,15 @@ void Journal::Dump() { kprintf("Journal %p\n", this); - kprintf(" log start: %ld\n", fVolume->LogStart()); - kprintf(" log end: %ld\n", fVolume->LogEnd()); + kprintf(" log start: %" B_PRId32 "\n", fVolume->LogStart()); + kprintf(" log end: %" B_PRId32 "\n", fVolume->LogEnd()); kprintf(" owner: %p\n", fOwner); - kprintf(" log size: %lu\n", fLogSize); - kprintf(" max transaction size: %lu\n", fMaxTransactionSize); - kprintf(" used: %lu\n", fUsed); - kprintf(" unwritten: %ld\n", fUnwrittenTransactions); - kprintf(" timestamp: %lld\n", fTimestamp); - kprintf(" transaction ID: %ld\n", fTransactionID); + kprintf(" log size: %" B_PRIu32 "\n", fLogSize); + kprintf(" max transaction size: %" B_PRIu32 "\n", fMaxTransactionSize); + kprintf(" used: %" B_PRIu32 "\n", fUsed); + kprintf(" unwritten: %" B_PRId32 "\n", fUnwrittenTransactions); + kprintf(" timestamp: %" B_PRId64 "\n", fTimestamp); + kprintf(" transaction ID: %" B_PRId32 "\n", fTransactionID); kprintf(" has subtransaction: %d\n", fHasSubtransaction); kprintf(" separate sub-trans.: %d\n", fSeparateSubTransactions); kprintf("entries:\n"); @@ -1102,8 +1102,8 @@ Journal::Dump() while (iterator.HasNext()) { LogEntry* entry = iterator.Next(); - kprintf(" %p %6ld %6lu %6lu\n", entry, entry->TransactionID(), - entry->Start(), entry->Length()); + kprintf(" %p %6" B_PRId32 " %6" B_PRIu32 " %6" B_PRIu32 "\n", entry, + entry->TransactionID(), entry->Start(), entry->Length()); } } From 700c8d3078c1caf65667b7cbb955527d524ff07c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 22 Jul 2012 11:36:50 +0100 Subject: [PATCH 121/273] Support building images for x86_64. Added a temporary Haiku64Image file that gets included instead of HaikuImage when building for x86_64, which I will add to as I port stuff. Images currently only include the boot loader, kernel and a bunch of add-ons. --- Jamfile | 6 +- build/jam/Haiku64Image | 401 +++++++++++++++++++++++++ src/add-ons/kernel/drivers/tty/tty.cpp | 24 +- 3 files changed, 418 insertions(+), 13 deletions(-) create mode 100644 build/jam/Haiku64Image diff --git a/Jamfile b/Jamfile index 929c395efa..9a446f8ad0 100644 --- a/Jamfile +++ b/Jamfile @@ -173,7 +173,11 @@ SubDir HAIKU_TOP ; UserBuildConfigRulePostBuildTargets ; # specify the Haiku image and network boot archive contents -include [ FDirName $(HAIKU_BUILD_RULES_DIR) HaikuImage ] ; +if $(TARGET_ARCH) = x86_64 { + include [ FDirName $(HAIKU_BUILD_RULES_DIR) Haiku64Image ] ; +} else { + include [ FDirName $(HAIKU_BUILD_RULES_DIR) HaikuImage ] ; +} include [ FDirName $(HAIKU_BUILD_RULES_DIR) NetBootArchive ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) FloppyBootImage ] ; include [ FDirName $(HAIKU_BUILD_RULES_DIR) CDBootImage ] ; diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image new file mode 100644 index 0000000000..1b126d4b37 --- /dev/null +++ b/build/jam/Haiku64Image @@ -0,0 +1,401 @@ +# This file defines what ends up on the Haiku image (respectively in the Haiku +# installation directory) and it executes the rules building the image +# (respectively installing the files in the installation directory). + +# This is only temporary while x86_64 is still a work in progress, so I can +# easily add things to the image as I port them. + +local GPL_ONLY = ; +if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 { + GPL_ONLY = "" ; +} + +#HACK: remove when old ide code is removed! +local ATA_ONLY = ; +local IDE_ONLY = ; +if $(HAIKU_ATA_STACK) = 1 { + ATA_ONLY = "" ; +} else { + IDE_ONLY = "" ; +} + +SYSTEM_BIN = ; + +SYSTEM_APPS = ; + +SYSTEM_PREFERENCES = ; + +SYSTEM_DEMOS = ; + +SYSTEM_LIBS = ; + +PRIVATE_SYSTEM_LIBS = ; + +SYSTEM_SERVERS = ; + +SYSTEM_ADD_ONS_BUS_MANAGERS = $(ATA_ONLY)ata pci scsi config_manager ; +SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; + +# modules +AddFilesToHaikuImage system add-ons kernel bus_managers + : $(SYSTEM_ADD_ONS_BUS_MANAGERS) ; + +if $(HAIKU_ATA_STACK) = 1 { + AddFilesToHaikuImage system add-ons kernel busses ata + : generic_ide_pci ; +} + +AddFilesToHaikuImage system add-ons kernel debugger + : demangle ; +AddFilesToHaikuImage system add-ons kernel file_systems + : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; +AddFilesToHaikuImage system add-ons kernel generic + : $(ATA_ONLY)ata_adapter dpc locked_pool scsi_periph tty ; +AddFilesToHaikuImage system add-ons kernel partitioning_systems + : intel session ; + +AddFilesToHaikuImage system add-ons kernel cpu : generic_x86 ; + +# drivers +AddNewDriversToHaikuImage disk scsi : scsi_cd scsi_disk ; + +# legacy drivers +AddDriversToHaikuImage : console dprintf null + random tty zero ; + +# kernel +AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; + +# libs +AddLibrariesToHaikuHybridImage system lib + : $(SYSTEM_LIBS) $(PRIVATE_SYSTEM_LIBS) ; + +# servers +AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ; + +# apps +#AddFilesToHaikuImage system : runtime_loader ; +AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ; +AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ; +AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ; +AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ; + +#AddSymlinkToHaikuImage system bin : bash : sh ; +#AddSymlinkToHaikuImage system bin : less : more ; +#AddSymlinkToHaikuImage system bin : gzip : gunzip ; +#AddSymlinkToHaikuImage system bin : gzip : zcat ; +#AddSymlinkToHaikuImage system bin : zdiff : zcmp ; +#AddSymlinkToHaikuImage system bin : unzip : zipinfo ; +#AddSymlinkToHaikuImage system bin : gawk : awk ; +#AddSymlinkToHaikuImage system bin : grep : egrep ; +#AddSymlinkToHaikuImage system bin : grep : fgrep ; + + +# scripts and data files +local bootScripts = Bootscript Bootscript.cd SetupEnvironment Netscript + InstallerInitScript InstallerFinishScript ; +SEARCH on $(bootScripts) = [ FDirName $(HAIKU_TOP) data system boot ] ; +AddFilesToHaikuImage system boot : $(bootScripts) ; + +local userBootScripts = UserBootscript UserSetupEnvironment.sample ; +SEARCH on $(userBootScripts) = [ FDirName $(HAIKU_TOP) data config boot ] ; +AddFilesToHaikuImage home config boot : $(userBootScripts) ; + +# Add boot launch directory +AddDirectoryToHaikuImage home config boot launch ; + +local etcDir = [ FDirName $(HAIKU_TOP) data etc ] ; +local etcFiles = inputrc profile ; +etcFiles = $(etcFiles:G=etc) ; +SEARCH on $(etcFiles) = [ FDirName $(etcDir) ] ; +etcFiles += termcap sysless sysless.in ; +AddFilesToHaikuImage common etc : $(etcFiles) ; + +local profileFiles = [ Glob $(etcDir)/profile.d : *.sh ] ; +profileFiles = $(profileFiles:G=profile-d) ; +AddDirectoryToHaikuImage common etc profile.d ; +AddFilesToHaikuImage common etc profile.d : $(profileFiles) ; + +local fortuneFiles = [ Glob $(HAIKU_TOP)/data/system/data/fortunes + : [a-zA-Z0-9]* ] ; +fortuneFiles = $(fortuneFiles:G=data!fortunes) ; +AddFilesToHaikuImage system data fortunes : $(fortuneFiles) ; + +#local fontDir = [ FDirName $(HAIKU_TOP) data system data fonts ] ; +#local psFonts = [ Glob $(fontDir)/psfonts : *.afm *.pfb ] ; +#local ttFonts = [ Glob $(fontDir)/ttfonts : *.ttf ] ; +#AddFilesToHaikuImage system data fonts psfonts : $(psFonts) ; +#AddFilesToHaikuImage system data fonts ttfonts : $(ttFonts) ; + +local keymapFiles = [ Glob [ FDirName $(HAIKU_TOP) src data keymaps ] + : *.keymap ] ; +keymapFiles = $(keymapFiles:BG=keymap) ; +AddFilesToHaikuImage system data Keymaps : $(keymapFiles) ; +AddSymlinkToHaikuImage system data Keymaps : Swedish : Finnish ; +AddSymlinkToHaikuImage system data Keymaps : Slovene : Croatian ; +AddSymlinkToHaikuImage system data Keymaps : US-International : Brazilian ; + +# Copy keyboard layout files to the image one-by-one. +local keyboardLayoutsDir + = [ FDirName $(HAIKU_TOP) data system data KeyboardLayouts ] ; +local keyboardLayoutFiles = + "Generic 104-key" + "Generic 105-key International" + "Kinesis Advantage" + "Kinesis Ergo Elan International" + "TypeMatrix 2030" ; +keyboardLayoutFiles = $(keyboardLayoutFiles:G=keyboard-layout) ; +SEARCH on $(keyboardLayoutFiles) = $(keyboardLayoutsDir) ; +AddFilesToHaikuImage system data KeyboardLayouts + : $(keyboardLayoutFiles) ; + +# Add Apple Aluminum keyboard layout files to the image in an Apple Aluminum +# subdirectory. The subdirectory is turned into a submenu in the Layout menu +# of the Keymap preference app. +local appleAluminumDir + = [ FDirName $(HAIKU_TOP) data system data KeyboardLayouts + Apple\ Aluminum ] ; +local appleAluminumFiles = + "Apple Aluminium Extended International" + "Apple Aluminium International" + "Apple Aluminum (US)" + "Apple Aluminum Extended (US)" ; +appleAluminumFiles = $(appleAluminumFiles:G=keyboard-layout) ; +SEARCH on $(appleAluminumFiles) = $(appleAluminumDir) ; +AddFilesToHaikuImage system data KeyboardLayouts Apple\ Aluminum + : $(appleAluminumFiles) ; + +# Add ThinkPad keyboard layout files to the image in a ThinkPad +# subdirectory. The subdirectory is turned into a submenu in the Layout menu +# of the Keymap preference app. +local thinkpadDir + = [ FDirName $(HAIKU_TOP) data system data KeyboardLayouts ThinkPad ] ; +local thinkPadFiles = + "ThinkPad (US)" + "ThinkPad International" + "ThinkPad T400s (US)" + "ThinkPad T400s International" + "ThinkPad X1 (US)" + "ThinkPad X1 International" + "ThinkPad X100e (US)" + "ThinkPad X100e International" ; +thinkPadFiles = $(thinkPadFiles:G=keyboard-layout) ; +SEARCH on $(thinkPadFiles) = $(thinkpadDir) ; +AddFilesToHaikuImage system data KeyboardLayouts ThinkPad + : $(thinkPadFiles) ; + +local driverSettingsFiles = kernel ; +SEARCH on $(driverSettingsFiles) + = [ FDirName $(HAIKU_TOP) data settings kernel drivers ] ; +AddFilesToHaikuImage home config settings kernel drivers + : $(driverSettingsFiles) ; + +# boot loader +AddFilesToHaikuImage system : haiku_loader ; + +# boot module links +AddBootModuleSymlinksToHaikuImage + $(ATA_ONLY)ata pci config_manager dpc scsi $(ATA_ONLY)ata_adapter + locked_pool scsi_periph generic_ide_pci scsi_cd scsi_disk intel + bfs +; + +# create directories that will remain empty +AddDirectoryToHaikuImage common bin ; +AddDirectoryToHaikuImage common include ; +AddDirectoryToHaikuImage common lib ; +AddDirectoryToHaikuImage home Desktop ; +AddDirectoryToHaikuImage home config bin ; +AddDirectoryToHaikuImage home config lib ; +AddDirectoryToHaikuImage home mail ; +AddDirectoryToHaikuImage common var empty ; +AddDirectoryToHaikuImage common var log ; +AddDirectoryToHaikuImage common cache tmp ; + +AddDirectoryToHaikuImage home config add-ons kernel drivers bin ; +AddDirectoryToHaikuImage home config add-ons kernel drivers dev ; + +# licenses +CopyDirectoryToHaikuImage system data + : [ FDirName $(HAIKU_TOP) data system data licenses ] + : licenses : -x .svn ; + +# Copy documentation as per DiskUsage's license requirement. +CopyDirectoryToHaikuImage system documentation + : [ FDirName $(HAIKU_TOP) docs apps diskusage ] + : diskusage : -x .svn ; + + +#pragma mark - Optional Packages + + +HAIKU_IMAGE_OPTIONAL_PACKAGE_DESCRIPTIONS = ; + +include [ FDirName $(HAIKU_BUILD_RULES_DIR) OptionalPackages ] ; +include [ FDirName $(HAIKU_BUILD_RULES_DIR) OptionalTestPackages ] ; +include [ FDirName $(HAIKU_BUILD_RULES_DIR) OptionalLibPackages ] ; + +local optionalPackageDescriptions ; +if $(HAIKU_IMAGE_OPTIONAL_PACKAGE_DESCRIPTIONS) { + optionalPackageDescriptions = optional_package_descriptions ; + MakeLocate $(optionalPackageDescriptions) + : $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) ; + + Depends $(optionalPackageDescriptions) + : $(HAIKU_IMAGE_OPTIONAL_PACKAGE_DESCRIPTIONS) ; + + actions together BuildOptionalPackageDescriptions + { + cat $(2) > $(1) + } + + BuildOptionalPackageDescriptions $(optionalPackageDescriptions) + : $(HAIKU_IMAGE_OPTIONAL_PACKAGE_DESCRIPTIONS) ; +} + + +#pragma mark - User/Group Setup + + +# add the root user and the root and users groups +AddUserToHaikuImage $(HAIKU_ROOT_USER_NAME:E=baron) : 0 : 0 : /boot/home + : /bin/bash : $(HAIKU_ROOT_USER_REAL_NAME:E="Root User") ; +AddGroupToHaikuImage root : 0 : ; +AddGroupToHaikuImage users : 100 : ; + + +#pragma mark - Host Name + + +if $(HAIKU_IMAGE_HOST_NAME) { + actions BuildHaikuImageHostnameFile + { + echo "$(HAIKU_IMAGE_HOST_NAME)" > $(1) + } + + local file = hostname ; + Always $(file) ; + MakeLocate $(file) : $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) ; + BuildHaikuImageHostnameFile $(file) ; + AddFilesToHaikuImage common settings network : $(file) ; +} + + +#pragma mark - Build The Image + + +# Execute pre-image user config rules. +UserBuildConfigRulePreImage ; + +# Set image name and directory defaults and locate the image. +HAIKU_IMAGE_NAME ?= $(HAIKU_DEFAULT_IMAGE_NAME) ; +HAIKU_IMAGE_DIR ?= $(HAIKU_DEFAULT_IMAGE_DIR) ; +HAIKU_IMAGE = $(HAIKU_IMAGE_NAME) ; +HAIKU_IMAGE_SIZE ?= $(HAIKU_DEFAULT_IMAGE_SIZE) ; # 300 MB +HAIKU_IMAGE_LABEL ?= $(HAIKU_DEFAULT_IMAGE_LABEL) ; +MakeLocate $(HAIKU_IMAGE) : $(HAIKU_IMAGE_DIR) ; + +# Set the default installation directory. +HAIKU_INSTALL_DIR ?= $(HAIKU_DEFAULT_INSTALL_DIR) ; + +# the pseudo target all image contents is attached to +NotFile $(HAIKU_IMAGE_CONTAINER_NAME) ; + +# prepare the script that initializes the shell variables +HAIKU_IMAGE_INIT_VARIABLES_SCRIPT = haiku.image-init-vars ; +local script = $(HAIKU_IMAGE_INIT_VARIABLES_SCRIPT) ; +MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ; +Always $(script) ; + +AddVariableToScript $(script) : sourceDir : $(HAIKU_TOP) ; +AddVariableToScript $(script) : outputDir : $(HAIKU_OUTPUT_DIR) ; +AddVariableToScript $(script) : tmpDir : $(HAIKU_TMP_DIR) ; +AddVariableToScript $(script) : installDir : $(HAIKU_INSTALL_DIR) ; +#AddVariableToScript $(script) : isImage : 1 ; +AddVariableToScript $(script) : imageSize : $(HAIKU_IMAGE_SIZE) ; +AddVariableToScript $(script) : imageLabel : $(HAIKU_IMAGE_LABEL) ; +AddVariableToScript $(script) : addBuildCompatibilityLibDir + : $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) ; +AddVariableToScript $(script) : dontClearImage : $(HAIKU_DONT_CLEAR_IMAGE) ; +AddVariableToScript $(script) : updateOnly : [ IsUpdateHaikuImageOnly ] ; +AddVariableToScript $(script) : stripOptionalPackageDebugSymbols + : $(HAIKU_STRIP_DEBUG_FROM_OPTIONAL_PACKAGES) ; +AddTargetVariableToScript $(script) : addattr ; +AddTargetVariableToScript $(script) : bfs_shell : bfsShell ; +AddTargetVariableToScript $(script) : fs_shell_command : fsShellCommand ; +AddTargetVariableToScript $(script) : copyattr ; +AddTargetVariableToScript $(script) : create_image : createImage ; +AddTargetVariableToScript $(script) : makebootable ; +AddTargetVariableToScript $(script) : rc ; +AddTargetVariableToScript $(script) : resattr ; +AddTargetVariableToScript $(script) : unzip ; +AddTargetVariableToScript $(script) : vmdkimage ; +if $(HOST_RM_ATTRS_TARGET) { + AddTargetVariableToScript $(script) : $(HOST_RM_ATTRS_TARGET) : rmAttrs ; +} else { + AddVariableToScript $(script) : rmAttrs : rm ; +} + + +# create the other scripts +HAIKU_IMAGE_MAKE_DIRS_SCRIPT = haiku.image-make-dirs ; +HAIKU_IMAGE_COPY_FILES_SCRIPT = haiku.image-copy-files ; +HAIKU_IMAGE_EXTRACT_FILES_SCRIPT = haiku.image-extract-files ; +MakeLocate $(HAIKU_IMAGE_MAKE_DIRS_SCRIPT) $(HAIKU_IMAGE_COPY_FILES_SCRIPT) + $(HAIKU_IMAGE_EXTRACT_FILES_SCRIPT) : $(HAIKU_OUTPUT_DIR) ; + +CreateHaikuImageMakeDirectoriesScript $(HAIKU_IMAGE_MAKE_DIRS_SCRIPT) ; +CreateHaikuImageCopyFilesScript $(HAIKU_IMAGE_COPY_FILES_SCRIPT) ; +CreateHaikuImageExtractFilesScript $(HAIKU_IMAGE_EXTRACT_FILES_SCRIPT) ; + +# Convenience wrapper rule around BuildHaikuImage. +rule _BuildHaikuImage image : isImage : isVMwareImage +{ + # _BuildHaikuImage : : ; + # + + # build the image + # HAIKU_IMAGE_EARLY_USER_SCRIPTS, HAIKU_IMAGE_LATE_USER_SCRIPTS can be + # specified by the user. + BuildHaikuImage $(image) : + $(HAIKU_IMAGE_INIT_VARIABLES_SCRIPT) + $(HAIKU_IMAGE_EARLY_USER_SCRIPTS) + $(HAIKU_IMAGE_MAKE_DIRS_SCRIPT) + $(HAIKU_IMAGE_COPY_FILES_SCRIPT) + $(HAIKU_IMAGE_EXTRACT_FILES_SCRIPT) + $(HAIKU_IMAGE_LATE_USER_SCRIPTS) + : $(isImage) + : $(isVMwareImage) + ; + + # remove the scripts we have generated + RmTemps $(image) : + $(HAIKU_IMAGE_INIT_VARIABLES_SCRIPT) + $(HAIKU_IMAGE_MAKE_DIRS_SCRIPT) + $(HAIKU_IMAGE_COPY_FILES_SCRIPT) + $(HAIKU_IMAGE_EXTRACT_FILES_SCRIPT) + ; +} + +# build the image +_BuildHaikuImage $(HAIKU_IMAGE) : true ; +NotFile haiku-image ; +Depends haiku-image : $(HAIKU_IMAGE) ; + + +# install Haiku into a directory +NotFile install-haiku ; +_BuildHaikuImage install-haiku : 0 ; + + +# build the VMware image +HAIKU_VMWARE_IMAGE_NAME ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ; +HAIKU_VMWARE_IMAGE = $(HAIKU_VMWARE_IMAGE_NAME) ; +MakeLocate $(HAIKU_VMWARE_IMAGE) : $(HAIKU_IMAGE_DIR) ; + +_BuildHaikuImage $(HAIKU_VMWARE_IMAGE) : true : true ; +NotFile haiku-vmware-image ; +Depends haiku-vmware-image : $(HAIKU_VMWARE_IMAGE) ; + +# Execute post-image user config rules. +UserBuildConfigRulePostImage ; diff --git a/src/add-ons/kernel/drivers/tty/tty.cpp b/src/add-ons/kernel/drivers/tty/tty.cpp index d18d91c154..4cc10d1ee4 100644 --- a/src/add-ons/kernel/drivers/tty/tty.cpp +++ b/src/add-ons/kernel/drivers/tty/tty.cpp @@ -1480,14 +1480,14 @@ tty_write_to_tty_slave_unsafe(tty_cookie* sourceCookie, const char* data, static void dump_tty_settings(struct tty_settings& settings) { - kprintf(" pgrp_id: %ld\n", settings.pgrp_id); - kprintf(" session_id: %ld\n", settings.session_id); + kprintf(" pgrp_id: %" B_PRId32 "\n", settings.pgrp_id); + kprintf(" session_id: %" B_PRId32 "\n", settings.session_id); kprintf(" termios:\n"); - kprintf(" c_iflag: 0x%08lx\n", settings.termios.c_iflag); - kprintf(" c_oflag: 0x%08lx\n", settings.termios.c_oflag); - kprintf(" c_cflag: 0x%08lx\n", settings.termios.c_cflag); - kprintf(" c_lflag: 0x%08lx\n", settings.termios.c_lflag); + kprintf(" c_iflag: 0x%08" B_PRIx32 "\n", settings.termios.c_iflag); + kprintf(" c_oflag: 0x%08" B_PRIx32 "\n", settings.termios.c_oflag); + kprintf(" c_cflag: 0x%08" B_PRIx32 "\n", settings.termios.c_cflag); + kprintf(" c_lflag: 0x%08" B_PRIx32 "\n", settings.termios.c_lflag); kprintf(" c_line: %d\n", settings.termios.c_line); kprintf(" c_ispeed: %u\n", settings.termios.c_ispeed); kprintf(" c_ospeed: %u\n", settings.termios.c_ospeed); @@ -1504,15 +1504,15 @@ static void dump_tty_struct(struct tty& tty) { kprintf(" tty @: %p\n", &tty); - kprintf(" index: %ld\n", tty.index); + kprintf(" index: %" B_PRId32 "\n", tty.index); kprintf(" is_master: %s\n", tty.is_master ? "true" : "false"); - kprintf(" open_count: %ld\n", tty.open_count); + kprintf(" open_count: %" B_PRId32 "\n", tty.open_count); kprintf(" select_pool: %p\n", tty.select_pool); - kprintf(" pending_eof: %lu\n", tty.pending_eof); + kprintf(" pending_eof: %" B_PRIu32 "\n", tty.pending_eof); kprintf(" lock: %p\n", tty.lock); kprintf(" input_buffer:\n"); - kprintf(" first: %ld\n", tty.input_buffer.first); + kprintf(" first: %" B_PRId32 "\n", tty.input_buffer.first); kprintf(" in: %lu\n", tty.input_buffer.in); kprintf(" size: %lu\n", tty.input_buffer.size); kprintf(" buffer: %p\n", tty.input_buffer.buffer); @@ -1782,7 +1782,7 @@ tty_ioctl(tty_cookie* cookie, uint32 op, void* buffer, size_t length) // wait for event (timeout if !NULL) case TCVTIME: // BeOS (bigtime_t*) set highrez VTIME case 'ochr': // BeOS (int*) same as ichr for write - dprintf("tty: unsupported legacy opcode %lu\n", op); + dprintf("tty: unsupported legacy opcode %" B_PRIu32 "\n", op); // TODO ? break; @@ -1791,7 +1791,7 @@ tty_ioctl(tty_cookie* cookie, uint32 op, void* buffer, size_t length) break; case TCQUERYCONNECTED: // BeOS - dprintf("tty: unsupported legacy opcode %lu\n", op); + dprintf("tty: unsupported legacy opcode %" B_PRIu32 "\n", op); // BeOS didn't implement them anyway break; From 5afce632f385fe750150f4b05f567f0f980a888e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 22 Jul 2012 12:13:04 +0100 Subject: [PATCH 122/273] Demangle symbols in stack traces. Since the demangle debugger extension now gets loaded when booting from an image, use it in stack traces. Can't print argument values like on x86, however, since x86_64 uses registers to pass the first 6 arguments rather than the stack we can't easily get to them. --- src/system/kernel/arch/x86/arch_debug.cpp | 39 ++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_debug.cpp b/src/system/kernel/arch/x86/arch_debug.cpp index 0f3faa82a5..ce61320f30 100644 --- a/src/system/kernel/arch/x86/arch_debug.cpp +++ b/src/system/kernel/arch/x86/arch_debug.cpp @@ -321,8 +321,39 @@ print_demangled_call(const char* image, const char* symbol, addr_t args, // arguments. Maybe we need DWARF support in the kernel debugger. For now // just print out the function signature without the argument values. - // TODO x86_64. - return B_NOT_SUPPORTED; + static const size_t kBufferSize = 256; + char* buffer = (char*)debug_malloc(kBufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + + bool isObjectMethod; + const char* name = debug_demangle_symbol(symbol, buffer, kBufferSize, + &isObjectMethod); + if (name == NULL) { + debug_free(buffer); + return B_ERROR; + } + + kprintf("<%s> %s(", image, name); + + size_t length; + int32 type, i = 0; + uint32 cookie = 0; + while (debug_get_next_demangled_argument(&cookie, symbol, buffer, + kBufferSize, &type, &length) == B_OK) { + if (i++ > 0) + kprintf(", "); + + if (buffer[0]) + kprintf("%s", buffer); + else + kprintf("???"); + } + + debug_free(buffer); + + kprintf(")"); + return B_OK; } @@ -360,10 +391,10 @@ print_stack_frame(Thread* thread, addr_t ip, addr_t bp, addr_t nextBp, if (!exactMatch || !demangle || status != B_OK) { if (symbol != NULL) { - kprintf("<%s>:%s%s", image, symbol, + kprintf("<%s> %s%s", image, symbol, exactMatch ? "" : " (nearest)"); } else - kprintf("<%s@%p>:unknown", image, (void*)baseAddress); + kprintf("<%s@%p> ", image, (void*)baseAddress); } kprintf(" + %#04lx\n", ip - baseAddress); From aef19e3c95ba3047d6d95b2731c6ea66dbbfddab Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 22 Jul 2012 13:07:44 +0100 Subject: [PATCH 123/273] Implemented creation and destruction of user translation maps. --- .../paging/64bit/X86VMTranslationMap64Bit.cpp | 92 ++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp index 2217bfe16b..70ce26b320 100644 --- a/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp +++ b/src/system/kernel/arch/x86/paging/64bit/X86VMTranslationMap64Bit.cpp @@ -46,7 +46,68 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit() { TRACE("X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()\n"); - panic("X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit: TODO"); + if (fPagingStructures == NULL) + return; + + if (fPageMapper != NULL) { + phys_addr_t address; + vm_page* page; + + // Free all structures in the bottom half of the PML4 (user memory). + uint64* virtualPML4 = fPagingStructures->VirtualPML4(); + for (uint32 i = 0; i < 256; i++) { + if ((virtualPML4[i] & X86_64_PML4E_PRESENT) == 0) + continue; + + uint64* virtualPDPT = (uint64*)fPageMapper->GetPageTableAt( + virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK); + for (uint32 j = 0; j < 512; j++) { + if ((virtualPDPT[j] & X86_64_PDPTE_PRESENT) == 0) + continue; + + uint64* virtualPageDir = (uint64*)fPageMapper->GetPageTableAt( + virtualPDPT[j] & X86_64_PDPTE_ADDRESS_MASK); + for (uint32 k = 0; k < 512; k++) { + if ((virtualPageDir[k] & X86_64_PDE_PRESENT) == 0) + continue; + + address = virtualPageDir[k] & X86_64_PDE_ADDRESS_MASK; + page = vm_lookup_page(address / B_PAGE_SIZE); + if (page == NULL) { + panic("page table %u %u %u on invalid page %#" + B_PRIxPHYSADDR "\n", i, j, k, address); + } + + DEBUG_PAGE_ACCESS_START(page); + vm_page_set_state(page, PAGE_STATE_FREE); + } + + address = virtualPDPT[j] & X86_64_PDPTE_ADDRESS_MASK; + page = vm_lookup_page(address / B_PAGE_SIZE); + if (page == NULL) { + panic("page directory %u %u on invalid page %#" + B_PRIxPHYSADDR "\n", i, j, address); + } + + DEBUG_PAGE_ACCESS_START(page); + vm_page_set_state(page, PAGE_STATE_FREE); + } + + address = virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK; + page = vm_lookup_page(address / B_PAGE_SIZE); + if (page == NULL) { + panic("PDPT %u on invalid page %#" B_PRIxPHYSADDR "\n", i, + address); + } + + DEBUG_PAGE_ACCESS_START(page); + vm_page_set_state(page, PAGE_STATE_FREE); + } + + fPageMapper->Delete(); + } + + fPagingStructures->RemoveReference(); } @@ -71,7 +132,34 @@ X86VMTranslationMap64Bit::Init(bool kernel) fPagingStructures->Init(method->KernelVirtualPML4(), method->KernelPhysicalPML4()); } else { - panic("X86VMTranslationMap64Bit::Init(): TODO"); + // Allocate a physical page mapper. + status_t error = method->PhysicalPageMapper() + ->CreateTranslationMapPhysicalPageMapper(&fPageMapper); + if (error != B_OK) + return error; + + // Assuming that only the top 2 PML4 entries are occupied for the + // kernel. + STATIC_ASSERT(KERNEL_PMAP_BASE == 0xffffff0000000000); + STATIC_ASSERT(KERNEL_BASE == 0xffffff8000000000); + + // Allocate and clear the PML4. + uint64* virtualPML4 = (uint64*)memalign(B_PAGE_SIZE, B_PAGE_SIZE); + if (virtualPML4 == NULL) + return B_NO_MEMORY; + memset(virtualPML4, 0, B_PAGE_SIZE); + + // Copy the top 2 PML4 entries. + virtualPML4[510] = method->KernelVirtualPML4()[510]; + virtualPML4[511] = method->KernelVirtualPML4()[511]; + + // Look up the PML4 physical address. + phys_addr_t physicalPML4; + vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPML4, + &physicalPML4); + + // Initialize the paging structures. + fPagingStructures->Init(virtualPML4, physicalPML4); } return B_OK; From fd9f32c0db56a5cebdda79c329b479355bdde87c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 22 Jul 2012 14:59:42 +0100 Subject: [PATCH 124/273] Added some libroot bits for x86_64. Still some parts missing (the glibc bits + fenv.c), plus the TLS functions are only stubs. --- src/system/libroot/os/arch/x86_64/Jamfile | 17 +++++++ .../libroot/os/arch/x86_64/get_stack_frame.S | 22 ++++++++ .../libroot/os/arch/x86_64/syscalls.inc | 46 +++++++++++++++++ .../libroot/os/arch/x86_64/system_info.cpp | 16 ++++++ src/system/libroot/os/arch/x86_64/thread.cpp | 18 +++++++ src/system/libroot/os/arch/x86_64/time.cpp | 44 ++++++++++++++++ src/system/libroot/os/arch/x86_64/tls.cpp | 50 +++++++++++++++++++ src/system/libroot/os/syscalls.S | 3 ++ src/system/libroot/posix/arch/x86_64/Jamfile | 19 +++++++ .../libroot/posix/string/arch/x86_64/Jamfile | 8 +++ .../posix/string/arch/x86_64/arch_string.S | 17 +++++++ 11 files changed, 260 insertions(+) create mode 100644 src/system/libroot/os/arch/x86_64/Jamfile create mode 100644 src/system/libroot/os/arch/x86_64/get_stack_frame.S create mode 100644 src/system/libroot/os/arch/x86_64/syscalls.inc create mode 100644 src/system/libroot/os/arch/x86_64/system_info.cpp create mode 100644 src/system/libroot/os/arch/x86_64/thread.cpp create mode 100644 src/system/libroot/os/arch/x86_64/time.cpp create mode 100644 src/system/libroot/os/arch/x86_64/tls.cpp create mode 100644 src/system/libroot/posix/arch/x86_64/Jamfile create mode 100644 src/system/libroot/posix/string/arch/x86_64/Jamfile create mode 100644 src/system/libroot/posix/string/arch/x86_64/arch_string.S diff --git a/src/system/libroot/os/arch/x86_64/Jamfile b/src/system/libroot/os/arch/x86_64/Jamfile new file mode 100644 index 0000000000..72a195ed84 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/Jamfile @@ -0,0 +1,17 @@ +SubDir HAIKU_TOP src system libroot os arch x86_64 ; + +UsePrivateKernelHeaders ; + # TODO: Replace by "UsePrivateHeaders libroot" after resolving the TODO in + # time.c! +UsePrivateSystemHeaders ; + +MergeObject os_arch_$(TARGET_ARCH).o : + atomic.S + byteorder.S + get_stack_frame.S + system_info.cpp + system_time_asm.S + thread.cpp + time.cpp + tls.cpp +; diff --git a/src/system/libroot/os/arch/x86_64/get_stack_frame.S b/src/system/libroot/os/arch/x86_64/get_stack_frame.S new file mode 100644 index 0000000000..0eaee36523 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/get_stack_frame.S @@ -0,0 +1,22 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. +*/ + + +#include + + +/* void* get_stack_frame(void) */ +FUNCTION(get_stack_frame): + movq %rbp, %rax + ret +FUNCTION_END(get_stack_frame) + + +/* void* __arch_get_caller(void); */ +FUNCTION(__arch_get_caller): + movq 8(%rbp), %rax + ret +FUNCTION_END(__arch_get_caller) + diff --git a/src/system/libroot/os/arch/x86_64/syscalls.inc b/src/system/libroot/os/arch/x86_64/syscalls.inc new file mode 100644 index 0000000000..f318d59c39 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/syscalls.inc @@ -0,0 +1,46 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +// The kernel follows the AMD64 ABI for parameter passing (first 6 arguments in +// registers and the remaining ones in on the stack), except that RCX is used +// by SYSCALL so it is moved to R10. Syscall number goes in RAX. + + +#define _SYSCALL(name, n) \ + .align 8; \ + FUNCTION(name): \ + movq %rcx, %r10; \ + movq $n, %rax; \ + syscall; \ + ret; \ + FUNCTION_END(name) + + +#define SYSCALL0(name, n) _SYSCALL(name, n) +#define SYSCALL1(name, n) _SYSCALL(name, n) +#define SYSCALL2(name, n) _SYSCALL(name, n) +#define SYSCALL3(name, n) _SYSCALL(name, n) +#define SYSCALL4(name, n) _SYSCALL(name, n) +#define SYSCALL5(name, n) _SYSCALL(name, n) +#define SYSCALL6(name, n) _SYSCALL(name, n) +#define SYSCALL7(name, n) _SYSCALL(name, n) +#define SYSCALL8(name, n) _SYSCALL(name, n) +#define SYSCALL9(name, n) _SYSCALL(name, n) +#define SYSCALL10(name, n) _SYSCALL(name, n) +#define SYSCALL11(name, n) _SYSCALL(name, n) +#define SYSCALL12(name, n) _SYSCALL(name, n) +#define SYSCALL13(name, n) _SYSCALL(name, n) +#define SYSCALL14(name, n) _SYSCALL(name, n) +#define SYSCALL15(name, n) _SYSCALL(name, n) +#define SYSCALL16(name, n) _SYSCALL(name, n) +#define SYSCALL17(name, n) _SYSCALL(name, n) +#define SYSCALL18(name, n) _SYSCALL(name, n) +#define SYSCALL19(name, n) _SYSCALL(name, n) +#define SYSCALL20(name, n) _SYSCALL(name, n) + diff --git a/src/system/libroot/os/arch/x86_64/system_info.cpp b/src/system/libroot/os/arch/x86_64/system_info.cpp new file mode 100644 index 0000000000..03a3e4c440 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/system_info.cpp @@ -0,0 +1,16 @@ +/* + * Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include + + +status_t +get_cpuid(cpuid_info* info, uint32 eaxRegister, uint32 cpuNum) +{ + return _kern_get_cpuid(info, eaxRegister, cpuNum); +} + diff --git a/src/system/libroot/os/arch/x86_64/thread.cpp b/src/system/libroot/os/arch/x86_64/thread.cpp new file mode 100644 index 0000000000..7b12f02e39 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/thread.cpp @@ -0,0 +1,18 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include +#include "syscalls.h" + + +thread_id +find_thread(const char* name) +{ + // TODO x86_64: x86 is doing some TLS thing here. Should that be done here + // too? + return _kern_find_thread(name); +} + diff --git a/src/system/libroot/os/arch/x86_64/time.cpp b/src/system/libroot/os/arch/x86_64/time.cpp new file mode 100644 index 0000000000..8b95ed1c62 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/time.cpp @@ -0,0 +1,44 @@ +/* + * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include +#include +#include + + +void +__arch_init_time(real_time_data* data, bool setDefaults) +{ + uint32 conversionFactor; + uint64 conversionFactorNsecs; + + if (setDefaults) { + data->arch_data.system_time_offset = 0; + data->arch_data.system_time_conversion_factor = 100000; + } + + // TODO: this should only store a pointer to that value + // When resolving this TODO, also resolve the one in the Jamfile. + + conversionFactor = data->arch_data.system_time_conversion_factor; + conversionFactorNsecs = (uint64)conversionFactor * 1000; + + // The x86_64 system_time() implementation uses 64-bit multiplication and + // therefore shifting is not necessary for low frequencies (it's also not + // too likely that there'll be any x86_64 CPUs clocked under 1GHz). + __x86_setup_system_time((uint64)conversionFactor << 32, + conversionFactorNsecs); +} + + +bigtime_t +__arch_get_system_time_offset(struct real_time_data *data) +{ + //we don't use atomic_get64 because memory is read-only, maybe find another way to lock + return data->arch_data.system_time_offset; +} + diff --git a/src/system/libroot/os/arch/x86_64/tls.cpp b/src/system/libroot/os/arch/x86_64/tls.cpp new file mode 100644 index 0000000000..794c422090 --- /dev/null +++ b/src/system/libroot/os/arch/x86_64/tls.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +// TODO x86_64. +// Also want to add inline versions to support/TLS.h. + + +#ifndef _NO_INLINE_ASM +# define _NO_INLINE_ASM 1 +#endif + +#include +#include + +#include + + +int32 +tls_allocate(void) +{ + assert(0 && "tls_allocate: not implemented"); + return 0; +} + + +void* +tls_get(int32 index) +{ + assert(0 && "tls_get: not implemented"); + return NULL; +} + + +void** +tls_address(int32 index) +{ + assert(0 && "tls_address: not implemented"); + return NULL; +} + + +void +tls_set(int32 index, void* value) +{ + assert(0 && "tls_set: not implemented"); +} + diff --git a/src/system/libroot/os/syscalls.S b/src/system/libroot/os/syscalls.S index 770da146bc..b7b3e87b02 100644 --- a/src/system/libroot/os/syscalls.S +++ b/src/system/libroot/os/syscalls.S @@ -1,6 +1,9 @@ #ifdef ARCH_x86 # include "arch/x86/syscalls.inc" #endif +#ifdef ARCH_x86_64 +# include "arch/x86_64/syscalls.inc" +#endif #ifdef ARCH_alpha # include "arch/alpha/syscalls.inc" #endif diff --git a/src/system/libroot/posix/arch/x86_64/Jamfile b/src/system/libroot/posix/arch/x86_64/Jamfile new file mode 100644 index 0000000000..cbbe85108d --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/Jamfile @@ -0,0 +1,19 @@ +SubDir HAIKU_TOP src system libroot posix arch x86_64 ; + +UsePrivateSystemHeaders ; + +local genericSources = + setjmp_save_sigs.c + longjmp_return.c +; + +MergeObject posix_arch_$(TARGET_ARCH).o : + #fenv.c + sigsetjmp.S + siglongjmp.S + + $(genericSources) +; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(SUBDIR) $(DOTDOT) generic ] ; diff --git a/src/system/libroot/posix/string/arch/x86_64/Jamfile b/src/system/libroot/posix/string/arch/x86_64/Jamfile new file mode 100644 index 0000000000..1c3ac217c0 --- /dev/null +++ b/src/system/libroot/posix/string/arch/x86_64/Jamfile @@ -0,0 +1,8 @@ +SubDir HAIKU_TOP src system libroot posix string arch x86_64 ; + +UsePrivateSystemHeaders ; + +MergeObject posix_string_arch_$(TARGET_ARCH).o : + arch_string.S +; + diff --git a/src/system/libroot/posix/string/arch/x86_64/arch_string.S b/src/system/libroot/posix/string/arch/x86_64/arch_string.S new file mode 100644 index 0000000000..8bbadb31ca --- /dev/null +++ b/src/system/libroot/posix/string/arch/x86_64/arch_string.S @@ -0,0 +1,17 @@ +/* + * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include +#include + + +FUNCTION(memcpy): + jmp *(USER_COMMPAGE_ADDR + COMMPAGE_ENTRY_X86_MEMCPY * 8) +FUNCTION_END(memcpy) + + +FUNCTION(memset): + jmp *(USER_COMMPAGE_ADDR + COMMPAGE_ENTRY_X86_MEMSET * 8) +FUNCTION_END(memset) From fe2e7327217d3e99738f88c2acd5beb45d6dbbed Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 23 Jul 2012 14:18:54 +0100 Subject: [PATCH 125/273] Avoid an unnecessary mov on syscalls with < 4 arguments. --- .../libroot/os/arch/x86_64/syscalls.inc | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/system/libroot/os/arch/x86_64/syscalls.inc b/src/system/libroot/os/arch/x86_64/syscalls.inc index f318d59c39..9a4881cddc 100644 --- a/src/system/libroot/os/arch/x86_64/syscalls.inc +++ b/src/system/libroot/os/arch/x86_64/syscalls.inc @@ -8,39 +8,48 @@ // The kernel follows the AMD64 ABI for parameter passing (first 6 arguments in -// registers and the remaining ones in on the stack), except that RCX is used -// by SYSCALL so it is moved to R10. Syscall number goes in RAX. +// registers and the remaining ones in on the stack), except that RCX (argument +// 4) is overwritten by the SYSCALL instruction, so it is moved to R10. Syscall +// number goes in RAX. -#define _SYSCALL(name, n) \ - .align 8; \ - FUNCTION(name): \ - movq %rcx, %r10; \ - movq $n, %rax; \ - syscall; \ - ret; \ +#define _SYSCALL_NO_RCX(name, n) \ + .align 8; \ + FUNCTION(name): \ + movq $n, %rax; \ + syscall; \ + ret; \ + FUNCTION_END(name) + +#define _SYSCALL_RCX(name, n) \ + .align 8; \ + FUNCTION(name): \ + movq %rcx, %r10; \ + movq $n, %rax; \ + syscall; \ + ret; \ FUNCTION_END(name) -#define SYSCALL0(name, n) _SYSCALL(name, n) -#define SYSCALL1(name, n) _SYSCALL(name, n) -#define SYSCALL2(name, n) _SYSCALL(name, n) -#define SYSCALL3(name, n) _SYSCALL(name, n) -#define SYSCALL4(name, n) _SYSCALL(name, n) -#define SYSCALL5(name, n) _SYSCALL(name, n) -#define SYSCALL6(name, n) _SYSCALL(name, n) -#define SYSCALL7(name, n) _SYSCALL(name, n) -#define SYSCALL8(name, n) _SYSCALL(name, n) -#define SYSCALL9(name, n) _SYSCALL(name, n) -#define SYSCALL10(name, n) _SYSCALL(name, n) -#define SYSCALL11(name, n) _SYSCALL(name, n) -#define SYSCALL12(name, n) _SYSCALL(name, n) -#define SYSCALL13(name, n) _SYSCALL(name, n) -#define SYSCALL14(name, n) _SYSCALL(name, n) -#define SYSCALL15(name, n) _SYSCALL(name, n) -#define SYSCALL16(name, n) _SYSCALL(name, n) -#define SYSCALL17(name, n) _SYSCALL(name, n) -#define SYSCALL18(name, n) _SYSCALL(name, n) -#define SYSCALL19(name, n) _SYSCALL(name, n) -#define SYSCALL20(name, n) _SYSCALL(name, n) +#define SYSCALL0(name, n) _SYSCALL_NO_RCX(name, n) +#define SYSCALL1(name, n) _SYSCALL_NO_RCX(name, n) +#define SYSCALL2(name, n) _SYSCALL_NO_RCX(name, n) +#define SYSCALL3(name, n) _SYSCALL_NO_RCX(name, n) +#define SYSCALL4(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL5(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL6(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL7(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL8(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL9(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL10(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL11(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL12(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL13(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL14(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL15(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL16(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL17(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL18(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL19(name, n) _SYSCALL_RCX(name, n) +#define SYSCALL20(name, n) _SYSCALL_RCX(name, n) From 07c6bd65b8aa82eae10c036e674799c1c5d16be9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 23 Jul 2012 14:20:29 +0100 Subject: [PATCH 126/273] Format string fixes for TRACE_{THREAD,TEAM}. --- src/system/kernel/team.cpp | 21 ++++++++++++--------- src/system/kernel/thread.cpp | 14 ++++++++------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index 0373b55c43..acdc915f26 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -976,7 +976,7 @@ ProcessGroup::ProcessGroup(pid_t id) ProcessGroup::~ProcessGroup() { - TRACE(("ProcessGroup::~ProcessGroup(): id = %ld\n", group->id)); + TRACE(("ProcessGroup::~ProcessGroup(): id = %" B_PRId32 "\n", id)); // If the group is in the orphaned check list, remove it. MutexLocker orphanedCheckLocker(sOrphanedCheckLock); @@ -1482,7 +1482,8 @@ team_create_thread_start_internal(void* args) team = thread->team; cache_node_launched(teamArgs->arg_count, teamArgs->flat_args); - TRACE(("team_create_thread_start: entry thread %ld\n", thread->id)); + TRACE(("team_create_thread_start: entry thread %" B_PRId32 "\n", + thread->id)); // Main stack area layout is currently as follows (starting from 0): // @@ -1604,8 +1605,8 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount, const char* path = flatArgs[0]; - TRACE(("load_image_internal: name '%s', args = %p, argCount = %ld\n", - path, flatArgs, argCount)); + TRACE(("load_image_internal: name '%s', args = %p, argCount = %" B_PRId32 + "\n", path, flatArgs, argCount)); // cut the path from the main thread name const char* threadName = strrchr(path, '/'); @@ -1804,8 +1805,9 @@ exec_team(const char* path, char**& _flatArgs, size_t flatArgsSize, const char* threadName; thread_id nubThreadID = -1; - TRACE(("exec_team(path = \"%s\", argc = %ld, envCount = %ld): team %ld\n", - path, argCount, envCount, team->id)); + TRACE(("exec_team(path = \"%s\", argc = %" B_PRId32 ", envCount = %" + B_PRId32 "): team %" B_PRId32 "\n", path, argCount, envCount, + team->id)); T(ExecTeam(path, argCount, flatArgs, envCount, flatArgs + argCount + 1)); @@ -1942,7 +1944,7 @@ fork_team(void) status_t status; int32 cookie; - TRACE(("fork_team(): team %ld\n", parentTeam->id)); + TRACE(("fork_team(): team %" B_PRId32 "\n", parentTeam->id)); if (parentTeam == team_get_kernel_team()) return B_NOT_ALLOWED; @@ -2304,7 +2306,8 @@ wait_for_child(pid_t child, uint32 flags, siginfo_t& _info) struct job_control_entry* freeDeathEntry = NULL; status_t status = B_OK; - TRACE(("wait_for_child(child = %ld, flags = %ld)\n", child, flags)); + TRACE(("wait_for_child(child = %" B_PRId32 ", flags = %" B_PRId32 ")\n", + child, flags)); T(WaitForChild(child, flags)); @@ -4078,7 +4081,7 @@ _user_load_image(const char* const* userFlatArgs, size_t flatArgsSize, int32 argCount, int32 envCount, int32 priority, uint32 flags, port_id errorPort, uint32 errorToken) { - TRACE(("_user_load_image: argc = %ld\n", argCount)); + TRACE(("_user_load_image: argc = %" B_PRId32 "\n", argCount)); if (argCount < 1) return B_BAD_VALUE; diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 76cb73c156..0519230bf5 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -1889,8 +1889,8 @@ thread_exit(void) struct thread_debug_info debugInfo; team_id teamID = team->id; - TRACE(("thread %ld exiting w/return code %#lx\n", thread->id, - thread->exit.status)); + TRACE(("thread %" B_PRId32 " exiting w/return code %#" B_PRIx32 "\n", + thread->id, thread->exit.status)); if (!are_interrupts_enabled()) panic("thread_exit() called with interrupts disabled!\n"); @@ -2095,7 +2095,8 @@ thread_exit(void) kernelTeam->Unlock(); } - TRACE(("thread_exit: thread %ld now a kernel thread!\n", thread->id)); + TRACE(("thread_exit: thread %" B_PRId32 " now a kernel thread!\n", + thread->id)); } free(threadDeathEntry); @@ -2232,7 +2233,7 @@ thread_at_kernel_entry(bigtime_t now) { Thread *thread = thread_get_current_thread(); - TRACE(("thread_at_kernel_entry: entry thread %ld\n", thread->id)); + TRACE(("thread_at_kernel_entry: entry thread %" B_PRId32 "\n", thread->id)); // track user time SpinLocker threadTimeLocker(thread->time_lock); @@ -2255,7 +2256,7 @@ thread_at_kernel_exit(void) { Thread *thread = thread_get_current_thread(); - TRACE(("thread_at_kernel_exit: exit thread %ld\n", thread->id)); + TRACE(("thread_at_kernel_exit: exit thread %" B_PRId32 "\n", thread->id)); handle_signals(thread); @@ -2279,7 +2280,8 @@ thread_at_kernel_exit_no_signals(void) { Thread *thread = thread_get_current_thread(); - TRACE(("thread_at_kernel_exit_no_signals: exit thread %ld\n", thread->id)); + TRACE(("thread_at_kernel_exit_no_signals: exit thread %" B_PRId32 "\n", + thread->id)); // track kernel time bigtime_t now = system_time(); From 370ab57d49a208f79ce3c5e9f92be13b58c48f18 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 23 Jul 2012 17:12:12 +0100 Subject: [PATCH 127/273] Initial userland support for x86_64. Userland switch is implemented, as is basic system call support (using SYSCALL/SYSRET). The system call handler is not yet complete: it doesn't handle more than 6 arguments, and does not perform all the necessary kernel entry/exit work (neither does the interrupt handler). However, this is sufficient for runtime_loader to start and print some debug output. --- headers/private/kernel/arch/x86/arch_cpu.h | 2 + .../x86/{x86_signals.cpp => 32/signals.cpp} | 0 .../{x86_signals_asm.S => 32/signals_asm.S} | 0 .../x86/{x86_syscalls.cpp => 32/syscalls.cpp} | 2 +- .../arch/x86/{syscall.S => 32/syscalls_asm.S} | 0 src/system/kernel/arch/x86/64/arch.S | 12 +++ src/system/kernel/arch/x86/64/interrupts.S | 84 ++++++++++++++++++- src/system/kernel/arch/x86/64/signals.cpp | 26 ++++++ src/system/kernel/arch/x86/64/stubs.cpp | 14 ---- src/system/kernel/arch/x86/64/syscalls.cpp | 58 +++++++++++++ src/system/kernel/arch/x86/64/thread.cpp | 45 +++++++++- src/system/kernel/arch/x86/Jamfile | 17 ++-- src/system/kernel/arch/x86/arch_commpage.cpp | 2 +- src/system/kernel/arch/x86/x86_syscalls.h | 27 ++++-- 14 files changed, 255 insertions(+), 34 deletions(-) rename src/system/kernel/arch/x86/{x86_signals.cpp => 32/signals.cpp} (100%) rename src/system/kernel/arch/x86/{x86_signals_asm.S => 32/signals_asm.S} (100%) rename src/system/kernel/arch/x86/{x86_syscalls.cpp => 32/syscalls.cpp} (98%) rename src/system/kernel/arch/x86/{syscall.S => 32/syscalls_asm.S} (100%) create mode 100644 src/system/kernel/arch/x86/64/signals.cpp create mode 100644 src/system/kernel/arch/x86/64/syscalls.cpp diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 836b27f7b1..dc0bafab4f 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -36,6 +36,8 @@ #define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 #define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 +#define IA32_MSR_EFER 0xc0000080 + // x86_64 MSRs. #define IA32_MSR_STAR 0xc0000081 #define IA32_MSR_LSTAR 0xc0000082 diff --git a/src/system/kernel/arch/x86/x86_signals.cpp b/src/system/kernel/arch/x86/32/signals.cpp similarity index 100% rename from src/system/kernel/arch/x86/x86_signals.cpp rename to src/system/kernel/arch/x86/32/signals.cpp diff --git a/src/system/kernel/arch/x86/x86_signals_asm.S b/src/system/kernel/arch/x86/32/signals_asm.S similarity index 100% rename from src/system/kernel/arch/x86/x86_signals_asm.S rename to src/system/kernel/arch/x86/32/signals_asm.S diff --git a/src/system/kernel/arch/x86/x86_syscalls.cpp b/src/system/kernel/arch/x86/32/syscalls.cpp similarity index 98% rename from src/system/kernel/arch/x86/x86_syscalls.cpp rename to src/system/kernel/arch/x86/32/syscalls.cpp index bd14bb0faf..3b3ffedba1 100644 --- a/src/system/kernel/arch/x86/x86_syscalls.cpp +++ b/src/system/kernel/arch/x86/32/syscalls.cpp @@ -76,7 +76,7 @@ init_amd_syscall_registers(void* dummy, int cpuNum) void -x86_initialize_commpage_syscall(void) +x86_initialize_syscall(void) { void* syscallCode = (void *)&_user_syscall_int; void* syscallCodeEnd = &_user_syscall_int_end; diff --git a/src/system/kernel/arch/x86/syscall.S b/src/system/kernel/arch/x86/32/syscalls_asm.S similarity index 100% rename from src/system/kernel/arch/x86/syscall.S rename to src/system/kernel/arch/x86/32/syscalls_asm.S diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 7ec20cb39a..cbaeec86cd 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -13,6 +13,7 @@ #include #include "asm_offsets.h" +#include "syscall_numbers.h" .text @@ -117,6 +118,17 @@ FUNCTION(x86_swap_pgdir): FUNCTION_END(x86_swap_pgdir) +/* thread exit stub - copied to the userspace stack in arch_thread_enter_uspace() */ +.align 8 +FUNCTION(x86_userspace_thread_exit): + movq %rax, %rdi + movq $SYSCALL_EXIT_THREAD, %rax + syscall +.align 8 +FUNCTION_END(x86_userspace_thread_exit) +SYMBOL(x86_end_userspace_thread_exit): + + null_idt_descr: .word 0 .quad 0 diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index 7987ed27a8..1169556828 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -10,6 +10,8 @@ #include #include "asm_offsets.h" +#include "syscall_numbers.h" +#include "syscall_table.h" // Push the remainder of the interrupt frame onto the stack. @@ -127,11 +129,15 @@ FUNCTION(int_bottom): // Frame pointer is the iframe. movq %rsp, %rbp + // TODO: Kernel entry work. + // Call the interrupt handler. movq %rsp, %rdi movq IFRAME_vector(%rsp), %rax call *gInterruptHandlerTable(, %rax, 8) + // TODO: Kernel exit work. + // Restore the saved registers. RESTORE_IFRAME() @@ -145,6 +151,73 @@ FUNCTION(int_bottom): FUNCTION_END(int_bottom) +// SYSCALL entry point. +FUNCTION(x86_64_syscall_entry): + // Upon entry, RSP still points at the user stack. Load the kernel GS + // segment base address, which points at the current thread's arch_thread + // structure. This contains our kernel stack pointer and a temporary + // scratch space to store the user stack pointer in before we can push it + // to the stack. + swapgs + movq %rsp, %gs:ARCH_THREAD_user_rsp + movq %gs:ARCH_THREAD_syscall_rsp, %rsp + + // Set up an iframe on the stack (R11 = saved RFLAGS, RCX = saved RIP). + push $USER_DATA_SEG // ss + push %gs:ARCH_THREAD_user_rsp // rsp + push %r11 // flags + push $USER_CODE_SEG // cs + push %rcx // ip + push $0 // error_code + push $0 // vector + PUSH_IFRAME_BOTTOM(IFRAME_TYPE_SYSCALL) + + // Frame pointer is the iframe. + movq %rsp, %rbp + + // TODO: Kernel entry work. + + // Check whether the syscall number is valid. + cmp $SYSCALL_COUNT, %rax + jae .Lbad_syscall_number + + // Get the system call table entry. Note I'm hardcoding the shift because + // sizeof(syscall_info) is 16 and scale factors of 16 aren't supported, + // so can't just do leaq kSyscallInfos(, %rax, SYSCALL_INFO_sizeof). + shl $4, %rax + leaq kSyscallInfos(, %rax, 1), %r12 + + // Move 4th argument to the correct register, it is put in R10 as RCX is + // used by SYSCALL. + movq %r10, %rcx + + // TODO: > 6 arguments. + + // No longer need interrupts disabled. + sti + + // Call the function and save its return value. + call *SYSCALL_INFO_function(%r12) + movq %rax, IFRAME_ax(%rsp) + + cli +.Lbad_syscall_number: + // TODO: Kernel exit work, check for canonical return address, syscall restart. + + // Restore the iframe and RCX/R11 for SYSRET. + RESTORE_IFRAME() + addq $16, %rsp + pop %rcx + addq $8, %rsp + pop %r11 + pop %rsp + + // Restore previous GS base and return. + swapgs + sysretq +FUNCTION_END(x86_64_syscall_entry) + + /*! \fn void x86_return_to_userland(iframe* frame) \brief Returns to the userland environment given by \a frame. @@ -158,5 +231,14 @@ FUNCTION_END(int_bottom) \param frame The iframe defining the userland environment. */ FUNCTION(x86_return_to_userland): - ud2a + movq %rdi, %rbp + movq %rbp, %rsp + + // TODO: Kernel exit work. + + // Restore the frame and return. + RESTORE_IFRAME() + addq $16, %rsp + swapgs + iretq FUNCTION_END(x86_return_to_userland) diff --git a/src/system/kernel/arch/x86/64/signals.cpp b/src/system/kernel/arch/x86/64/signals.cpp new file mode 100644 index 0000000000..0b07851096 --- /dev/null +++ b/src/system/kernel/arch/x86/64/signals.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "x86_signals.h" + +#include + +#include + +#include +#include +#include +#include + +#include "syscall_numbers.h" + + +void +x86_initialize_commpage_signal_handler() +{ + // TODO x86_64 +} + diff --git a/src/system/kernel/arch/x86/64/stubs.cpp b/src/system/kernel/arch/x86/64/stubs.cpp index 292572cc25..9ff4e715bc 100644 --- a/src/system/kernel/arch/x86/64/stubs.cpp +++ b/src/system/kernel/arch/x86/64/stubs.cpp @@ -37,20 +37,6 @@ #include -status_t -arch_commpage_init(void) -{ - return B_OK; -} - - -status_t -arch_commpage_init_post_cpus(void) -{ - return B_OK; -} - - // The software breakpoint instruction (int3). const uint8 kX86SoftwareBreakpoint[1] = { 0xcc }; diff --git a/src/system/kernel/arch/x86/64/syscalls.cpp b/src/system/kernel/arch/x86/64/syscalls.cpp new file mode 100644 index 0000000000..20bf44ef4e --- /dev/null +++ b/src/system/kernel/arch/x86/64/syscalls.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "x86_syscalls.h" + +#include + +#include +#include + + +// SYSCALL handler (in interrupts.S). +extern "C" void x86_64_syscall_entry(void); + + +static void +init_syscall_registers(void* dummy, int cpuNum) +{ + // Enable SYSCALL (EFER.SCE = 1). + x86_write_msr(IA32_MSR_EFER, x86_read_msr(IA32_MSR_EFER) | (1 << 0)); + + // Flags to clear upon entry. Want interrupts disabled and the direction + // flag cleared. + x86_write_msr(IA32_MSR_FMASK, X86_EFLAGS_INTERRUPT | X86_EFLAGS_DIRECTION); + + // Entry point address. + x86_write_msr(IA32_MSR_LSTAR, (addr_t)x86_64_syscall_entry); + + // Segments that will be set upon entry and return. This is very strange + // and requires a specific ordering of segments in the GDT. Upon entry: + // - CS is set to IA32_STAR[47:32] + // - SS is set to IA32_STAR[47:32] + 8 + // Upon return: + // - CS is set to IA32_STAR[63:48] + 16 + // - SS is set to IA32_STAR[63:48] + 8 + // From this we get: + // - Entry CS = KERNEL_CODE_SEG + // - Entry SS = KERNEL_CODE_SEG + 8 = KERNEL_DATA_SEG + // - Return CS = KERNEL_DATA_SEG + 16 = USER_CODE_SEG + // - Return SS = KERNEL_DATA_SEG + 8 = USER_DATA_SEG + x86_write_msr(IA32_MSR_STAR, ((uint64)(KERNEL_DATA_SEG | 3) << 48) + | ((uint64)KERNEL_CODE_SEG << 32)); +} + + +// #pragma mark - + + +void +x86_initialize_syscall(void) +{ + // SYSCALL/SYSRET are always available on x86_64 so we just use them, no + // need to use the commpage. Tell all CPUs to initialize the SYSCALL MSRs. + call_all_cpus_sync(&init_syscall_registers, NULL); +} diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index b4e9d8ac41..bd41ebaa3a 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -94,6 +94,9 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " "%p\n", _stackTop, function, data); + // Save the stack top for system call entry. + thread->arch_info.syscall_rsp = stackTop; + // x86_64 uses registers for argument passing, first argument in RDI, // however we don't save RDI on every context switch (there is no need // for us to: it is not callee-save, and only contains the first argument @@ -148,8 +151,46 @@ status_t arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, void* args2) { - panic("arch_thread_enter_userspace: TODO\n"); - return B_ERROR; + addr_t stackTop = thread->user_stack_base + thread->user_stack_size; + + TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " + "stackTop %#lx\n", entry, args1, args2, stackTop); + + // Copy the little stub that calls exit_thread() when the thread entry + // function returns. + // TODO: This will become a problem later if we want to support execute + // disable, the stack shouldn't really be executable. + size_t codeSize = (addr_t)x86_end_userspace_thread_exit + - (addr_t)x86_userspace_thread_exit; + stackTop -= codeSize; + if (user_memcpy((void*)stackTop, (const void*)&x86_userspace_thread_exit, + codeSize) != B_OK) + return B_BAD_ADDRESS; + + // Copy the address of the stub to the top of the stack to act as the + // return address. + addr_t codeAddr = stackTop; + stackTop -= sizeof(codeAddr); + if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) + != B_OK) + return B_BAD_ADDRESS; + + // Prepare the user iframe. + iframe frame = {}; + frame.type = IFRAME_TYPE_SYSCALL; + frame.si = (uint64)args2; + frame.di = (uint64)args1; + frame.ip = entry; + frame.cs = USER_CODE_SEG; + frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT + | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); + frame.sp = stackTop; + frame.ss = USER_DATA_SEG; + + // Return to userland. Never returns. + x86_initial_return_to_userland(thread, &frame); + + return B_OK; } diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 6fa9cea98d..579dda7d65 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -25,6 +25,8 @@ if $(TARGET_ARCH) = x86_64 { int.cpp interrupts.S stubs.cpp + signals.cpp + syscalls.cpp thread.cpp # paging @@ -47,17 +49,16 @@ if $(TARGET_ARCH) = x86_64 { cpuid.S int.cpp interrupts.S + signals.cpp + signals_asm.S + syscalls.cpp + syscalls_asm.S thread.cpp vm86.cpp - arch_commpage.cpp arch_user_debugger.cpp ioapic.cpp irq_routing_table.cpp - syscall.S - x86_signals.cpp - x86_signals_asm.S - x86_syscalls.cpp # paging x86_physical_page_mapper_large_memory.cpp @@ -76,6 +77,7 @@ if $(TARGET_ARCH) = x86_64 { local archGenericSources = arch_cpu.cpp + arch_commpage.cpp arch_debug.cpp arch_debug_console.cpp arch_elf.cpp @@ -114,8 +116,7 @@ KernelMergeObject kernel_arch_x86.o : CreateAsmStructOffsetsHeader asm_offsets.h : asm_offsets.cpp ; # We need to specify the dependency on the generated syscalls file explicitly. -Includes [ FGristFiles arch_interrupts.S arch_x86.S x86_signals.cpp - x86_signals_asm.S ] +Includes [ FGristFiles interrupts.S arch.S signals.cpp signals_asm.S ] : syscall_numbers.h ; -Includes [ FGristFiles arch_interrupts.S ] +Includes [ FGristFiles interrupts.S ] : syscall_table.h ; diff --git a/src/system/kernel/arch/x86/arch_commpage.cpp b/src/system/kernel/arch/x86/arch_commpage.cpp index 8b9cc0bdb6..ccb142f3c2 100644 --- a/src/system/kernel/arch/x86/arch_commpage.cpp +++ b/src/system/kernel/arch/x86/arch_commpage.cpp @@ -22,7 +22,7 @@ status_t arch_commpage_init_post_cpus(void) { // select the optimum syscall mechanism and patch the commpage - x86_initialize_commpage_syscall(); + x86_initialize_syscall(); // initialize the signal handler code in the commpage x86_initialize_commpage_signal_handler(); diff --git a/src/system/kernel/arch/x86/x86_syscalls.h b/src/system/kernel/arch/x86/x86_syscalls.h index 788e01a253..85ae6d7878 100644 --- a/src/system/kernel/arch/x86/x86_syscalls.h +++ b/src/system/kernel/arch/x86/x86_syscalls.h @@ -9,21 +9,34 @@ #include -extern void (*gX86SetSyscallStack)(addr_t stackTop); +void x86_initialize_syscall(); -void x86_initialize_commpage_syscall(); +#ifdef __x86_64__ static inline void x86_set_syscall_stack(addr_t stackTop) { - // TODO: x86_64 -#ifndef __x86_64__ - if (gX86SetSyscallStack != NULL) - gX86SetSyscallStack(stackTop); -#endif + // Nothing to do here, the thread's stack pointer is always accessible + // via the GS segment. } +#else + + +extern void (*gX86SetSyscallStack)(addr_t stackTop); + + +static inline void +x86_set_syscall_stack(addr_t stackTop) +{ + if (gX86SetSyscallStack != NULL) + gX86SetSyscallStack(stackTop); +} + + +#endif // __x86_64__ + #endif // _KERNEL_ARCH_X86_SYSCALLS_H From 6f1f972cafca49b8d664492322065346c3a58aeb Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 25 Jul 2012 08:56:47 +0100 Subject: [PATCH 128/273] Finished system call handler. The interrupt and system call handlers now perform all the necessary kernel entry/exit work, and the system call handler now handles calls with more than 6 arguments. Debugging and system call tracing hooks are not yet called, will be added when user debugging gets implemented. --- src/system/kernel/arch/x86/64/interrupts.S | 357 +++++++++++++++++++-- src/system/kernel/arch/x86/64/thread.cpp | 9 +- src/system/kernel/arch/x86/asm_offsets.cpp | 5 + 3 files changed, 338 insertions(+), 33 deletions(-) diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index 1169556828..3f2d621ea9 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -6,8 +6,11 @@ #include +#include + #include #include +#include #include "asm_offsets.h" #include "syscall_numbers.h" @@ -50,7 +53,73 @@ pop %rdx; \ pop %rcx; \ pop %rbx; \ - pop %rax; + pop %rax; \ + addq $16, %rsp; + + +// The macros below require R12 to contain the current thread pointer. R12 is +// callee-save so will be preserved through all function calls and only needs +// to be obtained once. R13 is used to store the system call start time, will +// also be preserved. + +#define LOCK_THREAD_TIME() \ + leaq THREAD_time_lock(%r12), %rdi; \ + call acquire_spinlock; + +#define UNLOCK_THREAD_TIME() \ + leaq THREAD_time_lock(%r12), %rdi; \ + call release_spinlock; \ + +#define UPDATE_THREAD_USER_TIME() \ + LOCK_THREAD_TIME() \ + \ + call system_time; \ + \ + /* Preserve system_time for post syscall debug */ \ + movq %rax, %r13; \ + \ + /* thread->user_time += now - thread->last_time; */ \ + subq THREAD_last_time(%r12), %rax; \ + addq %rax, THREAD_user_time(%r12); \ + \ + /* thread->last_time = now; */ \ + movq %r13, THREAD_last_time(%r12); \ + \ + /* thread->in_kernel = true; */ \ + movb $1, THREAD_in_kernel(%r12); \ + \ + UNLOCK_THREAD_TIME() + +#define UPDATE_THREAD_KERNEL_TIME() \ + LOCK_THREAD_TIME() \ + \ + call system_time; \ + movq %rax, %r13; \ + \ + /* thread->kernel_time += now - thread->last_time; */ \ + subq THREAD_last_time(%r12), %rax; \ + addq %rax, THREAD_kernel_time(%r12); \ + \ + /* thread->last_time = now; */ \ + movq %r13, THREAD_last_time(%r12); \ + \ + /* thread->in_kernel = false; */ \ + movb $0, THREAD_in_kernel(%r12); \ + \ + UNLOCK_THREAD_TIME() + +// TODO +#if 0 +#define STOP_USER_DEBUGGING() \ + testl $(THREAD_FLAGS_BREAKPOINTS_INSTALLED \ + | THREAD_FLAGS_SINGLE_STEP), THREAD_flags(%r12); \ + jz 1f; \ + call x86_exit_user_debug_at_kernel_entry; \ + 1: +#else +#define STOP_USER_DEBUGGING() +#endif + // The following code defines the interrupt service routines for all 256 // interrupts. It creates a block of handlers, each 16 bytes, that the IDT @@ -115,12 +184,11 @@ SYMBOL(isr_array): // Common interrupt handling code. -FUNCTION(int_bottom): - // If coming from user-mode, need to load the kernel GS segment base. +STATIC_FUNCTION(int_bottom): + // Coming from user-mode requires special handling. testl $3, 24(%rsp) - jz 1f - swapgs -1: + jnz int_bottom_user + // Push the rest of the interrupt frame to the stack. PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) @@ -129,26 +197,101 @@ FUNCTION(int_bottom): // Frame pointer is the iframe. movq %rsp, %rbp - // TODO: Kernel entry work. + // Set the RF (resume flag) in RFLAGS. This prevents an instruction + // breakpoint on the instruction we're returning to to trigger a debug + // exception. + orq $X86_EFLAGS_RESUME, IFRAME_flags(%rbp) // Call the interrupt handler. movq %rsp, %rdi movq IFRAME_vector(%rsp), %rax call *gInterruptHandlerTable(, %rax, 8) - // TODO: Kernel exit work. + // Restore the saved registers. + RESTORE_IFRAME() + + iretq +FUNCTION_END(int_bottom) + + +// Handler for an interrupt that occurred in user-mode. +STATIC_FUNCTION(int_bottom_user): + // Load the kerrnel GS segment base. + swapgs + + // Push the rest of the interrupt frame to the stack. + PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) + + cld + + // Frame pointer is the iframe. + movq %rsp, %rbp + + // Set the RF (resume flag) in RFLAGS. This prevents an instruction + // breakpoint on the instruction we're returning to to trigger a debug + // exception. + orq $X86_EFLAGS_RESUME, IFRAME_flags(%rbp) + + // Get thread pointer. + movq %gs:0, %r12 + + STOP_USER_DEBUGGING() + UPDATE_THREAD_USER_TIME() + + // Call the interrupt handler. + movq %rsp, %rdi + movq IFRAME_vector(%rsp), %rax + call *gInterruptHandlerTable(, %rax, 8) + + // If there are no signals pending or we're not debugging, we can avoid + // most of the work here, just need to update the kernel time. + testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ + | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED) \ + , THREAD_flags(%r12) + jnz .Lkernel_exit_work + + cli + + UPDATE_THREAD_KERNEL_TIME() // Restore the saved registers. RESTORE_IFRAME() - // Get rid of the error code and interrupt number, restore the previous - // GS base if returning to user-mode, and return. - addq $16, %rsp - testl $3, 8(%rsp) - jz 2f + // Restore the previous GS base and return. swapgs -2: iretq -FUNCTION_END(int_bottom) + iretq + +.Lkernel_exit_work: + // Slow path for return to userland. + + // Do we need to handle signals? + testl $(THREAD_FLAGS_SIGNALS_PENDING | THREAD_FLAGS_DEBUG_THREAD) \ + , THREAD_flags(%r12) + jnz .Lkernel_exit_handle_signals + cli + call thread_at_kernel_exit_no_signals + +.Lkernel_exit_work_done: + // Install breakpoints, if defined. TODO + //testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12) + //jz 1f + //movq %rbp, %rdi + //call x86_init_user_debug_at_kernel_exit +//1: + // Restore the saved registers. + RESTORE_IFRAME() + + // Restore the previous GS base and return. + swapgs + iretq + +.Lkernel_exit_handle_signals: + // thread_at_kernel_exit requires interrupts to be enabled, it will disable + // them after. + sti + call thread_at_kernel_exit + jmp .Lkernel_exit_work_done +FUNCTION_END(int_bottom_user) // SYSCALL entry point. @@ -172,41 +315,94 @@ FUNCTION(x86_64_syscall_entry): push $0 // vector PUSH_IFRAME_BOTTOM(IFRAME_TYPE_SYSCALL) + cld + // Frame pointer is the iframe. movq %rsp, %rbp - // TODO: Kernel entry work. + // Preserve call number (R14 is callee-save), get thread pointer. + movq %rax, %r14 + movq %gs:0, %r12 + + STOP_USER_DEBUGGING() + UPDATE_THREAD_USER_TIME() + + // No longer need interrupts disabled. + sti // Check whether the syscall number is valid. - cmp $SYSCALL_COUNT, %rax + cmpq $SYSCALL_COUNT, %r14 jae .Lbad_syscall_number // Get the system call table entry. Note I'm hardcoding the shift because // sizeof(syscall_info) is 16 and scale factors of 16 aren't supported, // so can't just do leaq kSyscallInfos(, %rax, SYSCALL_INFO_sizeof). - shl $4, %rax - leaq kSyscallInfos(, %rax, 1), %r12 + shlq $4, %r14 + leaq kSyscallInfos(, %r14, 1), %rax - // Move 4th argument to the correct register, it is put in R10 as RCX is - // used by SYSCALL. - movq %r10, %rcx + // Check the number of call arguments, greater than 6 (6 * 8 = 48) requires + // a stack copy. + movq SYSCALL_INFO_parameter_size(%rax), %rcx + cmpq $48, %rcx + ja .Lsyscall_stack_args - // TODO: > 6 arguments. + // Restore the arguments from the iframe. UPDATE_THREAD_USER_TIME() makes + // 2 function calls which means they may have been overwritten. Note that + // argument 4 is in R10 on the frame rather than RCX as RCX is used by + // SYSCALL. + movq IFRAME_di(%rbp), %rdi + movq IFRAME_si(%rbp), %rsi + movq IFRAME_dx(%rbp), %rdx + movq IFRAME_r10(%rbp), %rcx + movq IFRAME_r8(%rbp), %r8 + movq IFRAME_r9(%rbp), %r9 - // No longer need interrupts disabled. - sti + // TODO: pre-syscall tracing/debug // Call the function and save its return value. - call *SYSCALL_INFO_function(%r12) - movq %rax, IFRAME_ax(%rsp) + call *SYSCALL_INFO_function(%rax) + movq %rax, IFRAME_ax(%rbp) + + // TODO: post-syscall tracing + +.Lbad_syscall_number: +.Lsyscall_return: + // Clear the restarted flag. + testl $THREAD_FLAGS_SYSCALL_RESTARTED, THREAD_flags(%r12) + jz 2f +1: + movl THREAD_flags(%r12), %eax + movl %eax, %edx + andl $~THREAD_FLAGS_SYSCALL_RESTARTED, %edx + lock + cmpxchgl %edx, THREAD_flags(%r12) + jnz 1b +2: + testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ + | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED \ + | THREAD_FLAGS_RESTART_SYSCALL) \ + , THREAD_flags(%r12) + jnz .Lpost_syscall_work cli -.Lbad_syscall_number: - // TODO: Kernel exit work, check for canonical return address, syscall restart. + + UPDATE_THREAD_KERNEL_TIME() + + // If the return address is not canonical, return using the IRET path. + // On Intel's implementation of SYSRET, the canonical address check for the + // return address is performed before the switch to user mode, so a fault + // for a non-canonical address will be triggered in kernel mode. However, by + // then we will have switched onto the user stack meaning the kernel could + // be tricked into executing with the user RSP. Using IRET will handle + // non-canonical addresses properly. + movq IFRAME_user_sp(%rsp), %rax + sarq $47, %rax + incl %eax + cmpl $1, %eax + ja .Liret // Restore the iframe and RCX/R11 for SYSRET. RESTORE_IFRAME() - addq $16, %rsp pop %rcx addq $8, %rsp pop %r11 @@ -215,6 +411,96 @@ FUNCTION(x86_64_syscall_entry): // Restore previous GS base and return. swapgs sysretq + +.Lpost_syscall_work: + // TODO: post-syscall debugging + + // Do we need to handle signals? + testl $(THREAD_FLAGS_SIGNALS_PENDING | THREAD_FLAGS_DEBUG_THREAD) \ + , THREAD_flags(%r12) + jnz .Lpost_syscall_handle_signals + cli + call thread_at_kernel_exit_no_signals + +.Lpost_syscall_work_done: + // Handle syscall restarting. + testl $THREAD_FLAGS_RESTART_SYSCALL, THREAD_flags(%r12) + jz 1f + movq %rsp, %rdi + call x86_restart_syscall +1: + // Install breakpoints, if defined. TODO + //testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%r12) + //jz .Liret + //movq %rbp, %rdi + //call x86_init_user_debug_at_kernel_exit + + // On this return path it is possible that the frame has been modified, + // for example to execute a signal handler. In this case it is safer to + // return via IRET. + +.Liret: + // Restore the saved registers. + RESTORE_IFRAME() + + // Restore the previous GS base and return. + swapgs + iretq + +.Lpost_syscall_handle_signals: + call thread_at_kernel_exit + jmp .Lpost_syscall_work_done + +.Lsyscall_stack_args: + // Some arguments are on the stack, work out what we need to copy. 6 + // arguments (48 bytes) are already in registers. + // RAX = syscall table entry address, RCX = argument size. + subq $48, %rcx + + // Get the address to copy from. + movq IFRAME_user_sp(%rbp), %rsi + addq $8, %rsi + movabs $(USER_BASE + USER_SIZE), %rdx + cmp %rdx, %rsi + jae .Lbad_syscall_args + + // Make space on the stack. + subq %rcx, %rsp + movq %rsp, %rdi + + // Set a fault handler. + movq $.Lbad_syscall_args, THREAD_fault_handler(%r12) + + // Copy them by quadwords. + shrq $3, %rcx + rep + movsq + movq $0, THREAD_fault_handler(%r12) + + // Restore the register arguments from the iframe. + movq IFRAME_di(%rbp), %rdi + movq IFRAME_si(%rbp), %rsi + movq IFRAME_dx(%rbp), %rdx + movq IFRAME_r10(%rbp), %rcx + movq IFRAME_r8(%rbp), %r8 + movq IFRAME_r9(%rbp), %r9 + + // TODO: pre-syscall tracing/debug + + // Call the function and save its return value. + call *SYSCALL_INFO_function(%rax) + movq %rax, IFRAME_ax(%rbp) + + // TODO: post-syscall tracing + + // Restore the original stack pointer and return. + movq %rbp, %rsp + jmp .Lsyscall_return + +.Lbad_syscall_args: + movq $0, THREAD_fault_handler(%r12) + movq %rbp, %rsp + jmp .Lsyscall_return FUNCTION_END(x86_64_syscall_entry) @@ -234,11 +520,18 @@ FUNCTION(x86_return_to_userland): movq %rdi, %rbp movq %rbp, %rsp - // TODO: Kernel exit work. + // Perform kernel exit work. + movq %gs:0, %r12 + testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ + | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED) \ + , THREAD_flags(%r12) + jnz .Lkernel_exit_work + + // update the thread's kernel time and return + UPDATE_THREAD_KERNEL_TIME() // Restore the frame and return. RESTORE_IFRAME() - addq $16, %rsp swapgs iretq FUNCTION_END(x86_return_to_userland) diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index bd41ebaa3a..1d0434fde0 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -42,6 +42,13 @@ extern "C" void x86_64_thread_entry(); static arch_thread sInitialState; +void +x86_restart_syscall(iframe* frame) +{ + panic("x86_restart_syscall: TODO"); +} + + void x86_set_tls_context(Thread* thread) { @@ -95,7 +102,7 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, "%p\n", _stackTop, function, data); // Save the stack top for system call entry. - thread->arch_info.syscall_rsp = stackTop; + thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top; // x86_64 uses registers for argument passing, first argument in RDI, // however we don't save RDI on every context switch (there is no need diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index 469c4f71d4..e200c69c8a 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -56,6 +56,11 @@ dummy() DEFINE_OFFSET_MACRO(IFRAME, iframe, cs); DEFINE_OFFSET_MACRO(IFRAME, iframe, ax); DEFINE_OFFSET_MACRO(IFRAME, iframe, dx); + DEFINE_OFFSET_MACRO(IFRAME, iframe, di); + DEFINE_OFFSET_MACRO(IFRAME, iframe, si); + DEFINE_OFFSET_MACRO(IFRAME, iframe, r8); + DEFINE_OFFSET_MACRO(IFRAME, iframe, r9); + DEFINE_OFFSET_MACRO(IFRAME, iframe, r10); DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); DEFINE_OFFSET_MACRO(IFRAME, iframe, ip); DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); From ce35b7a68a5eb8d8f04416abafd5596a15805ab8 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 25 Jul 2012 15:00:50 +0100 Subject: [PATCH 129/273] Fixed broken build for x86. --- src/system/kernel/arch/x86/asm_offsets.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index e200c69c8a..65339ce38d 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -58,14 +58,15 @@ dummy() DEFINE_OFFSET_MACRO(IFRAME, iframe, dx); DEFINE_OFFSET_MACRO(IFRAME, iframe, di); DEFINE_OFFSET_MACRO(IFRAME, iframe, si); - DEFINE_OFFSET_MACRO(IFRAME, iframe, r8); - DEFINE_OFFSET_MACRO(IFRAME, iframe, r9); - DEFINE_OFFSET_MACRO(IFRAME, iframe, r10); DEFINE_OFFSET_MACRO(IFRAME, iframe, vector); DEFINE_OFFSET_MACRO(IFRAME, iframe, ip); DEFINE_OFFSET_MACRO(IFRAME, iframe, flags); DEFINE_OFFSET_MACRO(IFRAME, iframe, user_sp); -#ifdef __INTEL__ +#ifdef __x86_64__ + DEFINE_OFFSET_MACRO(IFRAME, iframe, r8); + DEFINE_OFFSET_MACRO(IFRAME, iframe, r9); + DEFINE_OFFSET_MACRO(IFRAME, iframe, r10); +#else DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); // struct vm86_iframe From e3ac2588e64059e0c140504e9acc8e73b3c36fdc Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 25 Jul 2012 15:05:21 +0100 Subject: [PATCH 130/273] Changed runtime_loader to use elf_* typedefs over Elf32_*. This means that it will be using ELF64 types on x86_64 rather than ELF32. The next step for supporting x86_64 is to implement relocations. --- .../private/runtime_loader/runtime_loader.h | 19 ++--- src/system/runtime_loader/elf.cpp | 42 +++++------ .../runtime_loader/elf_haiku_version.cpp | 16 ++-- src/system/runtime_loader/elf_haiku_version.h | 2 +- src/system/runtime_loader/elf_load_image.cpp | 42 +++++------ src/system/runtime_loader/elf_load_image.h | 2 +- .../runtime_loader/elf_symbol_lookup.cpp | 73 +++++++++---------- src/system/runtime_loader/elf_symbol_lookup.h | 14 ++-- src/system/runtime_loader/elf_versioning.cpp | 49 ++++++------- src/system/runtime_loader/images.cpp | 4 +- src/system/runtime_loader/runtime_loader.cpp | 3 +- .../runtime_loader/runtime_loader_private.h | 4 +- 12 files changed, 133 insertions(+), 137 deletions(-) diff --git a/headers/private/runtime_loader/runtime_loader.h b/headers/private/runtime_loader/runtime_loader.h index 4cdac83290..cc9b96cd98 100644 --- a/headers/private/runtime_loader/runtime_loader.h +++ b/headers/private/runtime_loader/runtime_loader.h @@ -15,6 +15,7 @@ #include #include +#include // #pragma mark - runtime loader libroot interface @@ -100,13 +101,13 @@ typedef struct image_t { // pointer to symbol participation data structures uint32 *symhash; - struct Elf32_Sym *syms; + elf_sym *syms; char *strtab; - struct Elf32_Rel *rel; + elf_rel *rel; int rel_len; - struct Elf32_Rela *rela; + elf_rela *rela; int rela_len; - struct Elf32_Rel *pltrel; + elf_rel *pltrel; int pltrel_len; uint32 num_needed; @@ -114,20 +115,20 @@ typedef struct image_t { // versioning related structures uint32 num_version_definitions; - struct Elf32_Verdef *version_definitions; + elf_verdef *version_definitions; uint32 num_needed_versions; - struct Elf32_Verneed *needed_versions; - Elf32_Versym *symbol_versions; + elf_verneed *needed_versions; + elf_versym *symbol_versions; elf_version_info *versions; uint32 num_versions; #ifdef __cplusplus - struct Elf32_Sym* (*find_undefined_symbol)(struct image_t* rootImage, + elf_sym* (*find_undefined_symbol)(struct image_t* rootImage, struct image_t* image, const SymbolLookupInfo& lookupInfo, struct image_t** foundInImage); #else - struct Elf32_Sym* (*find_undefined_symbol)(struct image_t* rootImage, + elf_sym* (*find_undefined_symbol)(struct image_t* rootImage, struct image_t* image, const struct SymbolLookupInfo* lookupInfo, struct image_t** foundInImage); diff --git a/src/system/runtime_loader/elf.cpp b/src/system/runtime_loader/elf.cpp index 5d3c880d4a..9415d73b55 100644 --- a/src/system/runtime_loader/elf.cpp +++ b/src/system/runtime_loader/elf.cpp @@ -18,7 +18,6 @@ #include -#include #include #include @@ -70,7 +69,7 @@ static const char * find_dt_rpath(image_t *image) { int i; - struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; + elf_dyn *d = (elf_dyn *)image->dynamic_ptr; for (i = 0; d[i].d_tag != DT_NULL; i++) { if (d[i].d_tag == DT_RPATH) @@ -84,7 +83,7 @@ find_dt_rpath(image_t *image) static status_t load_immediate_dependencies(image_t *image) { - struct Elf32_Dyn *d = (struct Elf32_Dyn *)image->dynamic_ptr; + elf_dyn *d = (elf_dyn *)image->dynamic_ptr; bool reportErrors = report_errors(); status_t status = B_OK; uint32 i, j; @@ -670,7 +669,7 @@ get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, // iterate through all the hash buckets until we've found the one for (i = 0; i < HASHTABSIZE(image); i++) { for (j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; if (count == num) { const char* symbolName = SYMNAME(image, symbol); @@ -680,9 +679,9 @@ get_nth_symbol(image_id imageID, int32 num, char *nameBuffer, void* location = (void*)(symbol->st_value + image->regions[0].delta); int32 type; - if (ELF32_ST_TYPE(symbol->st_info) == STT_FUNC) + if (symbol->Type() == STT_FUNC) type = B_SYMBOL_TYPE_TEXT; - else if (ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT) + else if (symbol->Type() == STT_OBJECT) type = B_SYMBOL_TYPE_DATA; else type = B_SYMBOL_TYPE_ANY; @@ -721,14 +720,14 @@ get_nearest_symbol_at_address(void* address, image_id* _imageID, return B_BAD_VALUE; } - struct Elf32_Sym* foundSymbol = NULL; + elf_sym* foundSymbol = NULL; addr_t foundLocation = (addr_t)NULL; bool found = false; for (uint32 i = 0; i < HASHTABSIZE(image) && !found; i++) { for (int32 j = HASHBUCKETS(image)[i]; j != STN_UNDEF; j = HASHCHAINS(image)[j]) { - struct Elf32_Sym *symbol = &image->syms[j]; + elf_sym *symbol = &image->syms[j]; addr_t location = symbol->st_value + image->regions[0].delta; if (location <= (addr_t)address && location >= foundLocation) { @@ -753,9 +752,9 @@ get_nearest_symbol_at_address(void* address, image_id* _imageID, *_symbolName = SYMNAME(image, foundSymbol); if (_type != NULL) { - if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_FUNC) + if (foundSymbol->Type() == STT_FUNC) *_type = B_SYMBOL_TYPE_TEXT; - else if (ELF32_ST_TYPE(foundSymbol->st_info) == STT_OBJECT) + else if (foundSymbol->Type() == STT_OBJECT) *_type = B_SYMBOL_TYPE_DATA; else *_type = B_SYMBOL_TYPE_ANY; @@ -831,14 +830,14 @@ get_library_symbol(void* handle, void* caller, const char* symbolName, if (handle == RTLD_DEFAULT || handle == RLD_GLOBAL_SCOPE) { // look in the default scope image_t* image; - Elf32_Sym* symbol = find_undefined_symbol_global(gProgramImage, + elf_sym* symbol = find_undefined_symbol_global(gProgramImage, gProgramImage, SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_ANY, NULL, LOOKUP_FLAG_DEFAULT_VERSION), &image); if (symbol != NULL) { *_location = (void*)(symbol->st_value + image->regions[0].delta); - int32 symbolType = ELF32_ST_TYPE(symbol->st_info) == STT_FUNC + int32 symbolType = symbol->Type() == STT_FUNC ? B_SYMBOL_TYPE_TEXT : B_SYMBOL_TYPE_DATA; patch_defined_symbol(image, symbolName, _location, &symbolType); status = B_OK; @@ -864,7 +863,7 @@ get_library_symbol(void* handle, void* caller, const char* symbolName, bool hitCallerImage = false; set_image_flags_recursively(callerImage, RFLAG_USE_FOR_RESOLVING); - Elf32_Sym* candidateSymbol = NULL; + elf_sym* candidateSymbol = NULL; image_t* candidateImage = NULL; image_t* image = get_loaded_images().head; @@ -883,14 +882,14 @@ get_library_symbol(void* handle, void* caller, const char* symbolName, continue; } - struct Elf32_Sym *symbol = find_symbol(image, + elf_sym *symbol = find_symbol(image, SymbolLookupInfo(symbolName, B_SYMBOL_TYPE_TEXT, NULL, LOOKUP_FLAG_DEFAULT_VERSION)); if (symbol == NULL) continue; // found a symbol - bool isWeak = ELF32_ST_BIND(symbol->st_info) == STB_WEAK; + bool isWeak = symbol->Bind() == STB_WEAK; if (candidateImage == NULL || !isWeak) { candidateSymbol = symbol; candidateImage = image; @@ -932,7 +931,7 @@ status_t get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) { uint32 i, j, searchIndex = *cookie; - struct Elf32_Dyn *dynamicSection; + elf_dyn *dynamicSection; image_t *image; if (_name == NULL) @@ -946,7 +945,7 @@ get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) return B_BAD_IMAGE_ID; } - dynamicSection = (struct Elf32_Dyn *)image->dynamic_ptr; + dynamicSection = (elf_dyn *)image->dynamic_ptr; if (dynamicSection == NULL || image->num_needed <= searchIndex) { rld_unlock(); return B_ENTRY_NOT_FOUND; @@ -976,15 +975,14 @@ get_next_image_dependency(image_id id, uint32 *cookie, const char **_name) /*! Read and verify the ELF header */ status_t -elf_verify_header(void *header, int32 length) +elf_verify_header(void *header, size_t length) { int32 programSize, sectionSize; - if (length < (int32)sizeof(struct Elf32_Ehdr)) + if (length < sizeof(elf_ehdr)) return B_NOT_AN_EXECUTABLE; - return parse_elf_header((struct Elf32_Ehdr *)header, &programSize, - §ionSize); + return parse_elf_header((elf_ehdr *)header, &programSize, §ionSize); } @@ -1029,7 +1027,7 @@ rldelf_init(void) // create the debug area { - int32 size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); + size_t size = TO_PAGE_SIZE(sizeof(runtime_loader_debug_area)); runtime_loader_debug_area *area; area_id areaID = _kern_create_area(RUNTIME_LOADER_DEBUG_AREA_NAME, diff --git a/src/system/runtime_loader/elf_haiku_version.cpp b/src/system/runtime_loader/elf_haiku_version.cpp index 0646eb850f..75c01c8abe 100644 --- a/src/system/runtime_loader/elf_haiku_version.cpp +++ b/src/system/runtime_loader/elf_haiku_version.cpp @@ -20,7 +20,7 @@ static bool -analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader, +analyze_object_gcc_version(int fd, image_t* image, elf_ehdr& eheader, int32 sheaderSize, char* buffer, size_t bufferSize) { if (sheaderSize > (int)bufferSize) { @@ -38,8 +38,8 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader, } // load the string section - Elf32_Shdr* sectionHeader - = (Elf32_Shdr*)(buffer + eheader.e_shstrndx * eheader.e_shentsize); + elf_shdr* sectionHeader + = (elf_shdr*)(buffer + eheader.e_shstrndx * eheader.e_shentsize); if (sheaderSize + sectionHeader->sh_size > bufferSize) { FATAL("%s: Buffer not big enough for section string section\n", @@ -60,7 +60,7 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader, off_t commentOffset = 0; size_t commentSize = 0; for (uint32 i = 0; i < eheader.e_shnum; i++) { - sectionHeader = (Elf32_Shdr*)(buffer + i * eheader.e_shentsize); + sectionHeader = (elf_shdr*)(buffer + i * eheader.e_shentsize); const char* sectionName = sectionStrings + sectionHeader->sh_name; if (sectionHeader->sh_name != 0 && strcmp(sectionName, ".comment") == 0) { @@ -189,16 +189,16 @@ analyze_object_gcc_version(int fd, image_t* image, Elf32_Ehdr& eheader, void -analyze_image_haiku_version_and_abi(int fd, image_t* image, Elf32_Ehdr& eheader, +analyze_image_haiku_version_and_abi(int fd, image_t* image, elf_ehdr& eheader, int32 sheaderSize, char* buffer, size_t bufferSize) { // Haiku API version - struct Elf32_Sym* symbol = find_symbol(image, + elf_sym* symbol = find_symbol(image, SymbolLookupInfo(B_SHARED_OBJECT_HAIKU_VERSION_VARIABLE_NAME, B_SYMBOL_TYPE_DATA)); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF && symbol->st_value > 0 - && ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT + && symbol->Type() == STT_OBJECT && symbol->st_size >= sizeof(uint32)) { image->api_version = *(uint32*)(symbol->st_value + image->regions[0].delta); @@ -211,7 +211,7 @@ analyze_image_haiku_version_and_abi(int fd, image_t* image, Elf32_Ehdr& eheader, B_SYMBOL_TYPE_DATA)); if (symbol != NULL && symbol->st_shndx != SHN_UNDEF && symbol->st_value > 0 - && ELF32_ST_TYPE(symbol->st_info) == STT_OBJECT + && symbol->Type() == STT_OBJECT && symbol->st_size >= sizeof(uint32)) { image->abi = *(uint32*)(symbol->st_value + image->regions[0].delta); } else diff --git a/src/system/runtime_loader/elf_haiku_version.h b/src/system/runtime_loader/elf_haiku_version.h index 4c8353df4a..a24cc6055b 100644 --- a/src/system/runtime_loader/elf_haiku_version.h +++ b/src/system/runtime_loader/elf_haiku_version.h @@ -9,7 +9,7 @@ void analyze_image_haiku_version_and_abi(int fd, image_t* image, - Elf32_Ehdr& eheader, int32 sheaderSize, char* buffer, + elf_ehdr& eheader, int32 sheaderSize, char* buffer, size_t bufferSize); diff --git a/src/system/runtime_loader/elf_load_image.cpp b/src/system/runtime_loader/elf_load_image.cpp index 97f6988aa3..380db38dab 100644 --- a/src/system/runtime_loader/elf_load_image.cpp +++ b/src/system/runtime_loader/elf_load_image.cpp @@ -36,12 +36,12 @@ get_program_path() static int32 count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) { - struct Elf32_Phdr* pheaders; + elf_phdr* pheaders; int32 count = 0; int i; for (i = 0; i < phnum; i++) { - pheaders = (struct Elf32_Phdr*)(buff + i * phentsize); + pheaders = (elf_phdr*)(buff + i * phentsize); switch (pheaders->p_type) { case PT_NULL: @@ -78,7 +78,7 @@ count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) // we don't use it break; default: - FATAL("%s: Unhandled pheader type in count 0x%lx\n", + FATAL("%s: Unhandled pheader type in count 0x%" B_PRIx32 "\n", imagePath, pheaders->p_type); return B_BAD_DATA; } @@ -91,13 +91,13 @@ count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) static status_t parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) { - struct Elf32_Phdr* pheader; + elf_phdr* pheader; int regcount; int i; regcount = 0; for (i = 0; i < phnum; i++) { - pheader = (struct Elf32_Phdr*)(buff + i * phentsize); + pheader = (elf_phdr*)(buff + i * phentsize); switch (pheader->p_type) { case PT_NULL: @@ -194,7 +194,7 @@ parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) // we don't use it break; default: - FATAL("%s: Unhandled pheader type in parse 0x%lx\n", + FATAL("%s: Unhandled pheader type in parse 0x%" B_PRIx32 "\n", image->path, pheader->p_type); return B_BAD_DATA; } @@ -227,7 +227,7 @@ assert_dynamic_loadable(image_t* image) static bool parse_dynamic_segment(image_t* image) { - struct Elf32_Dyn* d; + elf_dyn* d; int i; int sonameOffset = -1; @@ -235,7 +235,7 @@ parse_dynamic_segment(image_t* image) image->syms = 0; image->strtab = 0; - d = (struct Elf32_Dyn*)image->dynamic_ptr; + d = (elf_dyn*)image->dynamic_ptr; if (!d) return true; @@ -253,18 +253,18 @@ parse_dynamic_segment(image_t* image) = (char*)(d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_SYMTAB: - image->syms = (struct Elf32_Sym*) + image->syms = (elf_sym*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_REL: - image->rel = (struct Elf32_Rel*) + image->rel = (elf_rel*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_RELSZ: image->rel_len = d[i].d_un.d_val; break; case DT_RELA: - image->rela = (struct Elf32_Rela*) + image->rela = (elf_rela*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_RELASZ: @@ -272,7 +272,7 @@ parse_dynamic_segment(image_t* image) break; case DT_JMPREL: // procedure linkage table relocations - image->pltrel = (struct Elf32_Rel*) + image->pltrel = (elf_rel*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_PLTRELSZ: @@ -290,18 +290,18 @@ parse_dynamic_segment(image_t* image) sonameOffset = d[i].d_un.d_val; break; case DT_VERSYM: - image->symbol_versions = (Elf32_Versym*) + image->symbol_versions = (elf_versym*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_VERDEF: - image->version_definitions = (Elf32_Verdef*) + image->version_definitions = (elf_verdef*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_VERDEFNUM: image->num_version_definitions = d[i].d_un.d_val; break; case DT_VERNEED: - image->needed_versions = (Elf32_Verneed*) + image->needed_versions = (elf_verneed*) (d[i].d_un.d_ptr + image->regions[0].delta); break; case DT_VERNEEDNUM: @@ -350,19 +350,19 @@ parse_dynamic_segment(image_t* image) status_t -parse_elf_header(struct Elf32_Ehdr* eheader, int32* _pheaderSize, +parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize, int32* _sheaderSize) { if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) return B_NOT_AN_EXECUTABLE; - if (eheader->e_ident[4] != ELFCLASS32) + if (eheader->e_ident[4] != ELF_CLASS) return B_NOT_AN_EXECUTABLE; if (eheader->e_phoff == 0) return B_NOT_AN_EXECUTABLE; - if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) + if (eheader->e_phentsize < sizeof(elf_phdr)) return B_NOT_AN_EXECUTABLE; *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; @@ -389,7 +389,7 @@ load_image(char const* name, image_type type, const char* rpath, status_t status; int fd; - struct Elf32_Ehdr eheader; + elf_ehdr eheader; // Have we already loaded that image? Don't check for add-ons -- we always // reload them. @@ -480,8 +480,8 @@ load_image(char const* name, image_type type, const char* rpath, numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum, eheader.e_phentsize); if (numRegions <= 0) { - FATAL("%s: Troubles parsing Program headers, numRegions = %ld\n", - path, numRegions); + FATAL("%s: Troubles parsing Program headers, numRegions = %" B_PRId32 + "\n", path, numRegions); status = B_BAD_DATA; goto err1; } diff --git a/src/system/runtime_loader/elf_load_image.h b/src/system/runtime_loader/elf_load_image.h index 3fec7ec485..e7c4e23367 100644 --- a/src/system/runtime_loader/elf_load_image.h +++ b/src/system/runtime_loader/elf_load_image.h @@ -8,7 +8,7 @@ #include "runtime_loader_private.h" -status_t parse_elf_header(struct Elf32_Ehdr* eheader, int32* _pheaderSize, +status_t parse_elf_header(elf_ehdr* eheader, int32* _pheaderSize, int32* _sheaderSize); status_t load_image(char const* name, image_type type, const char* rpath, image_t** _image); diff --git a/src/system/runtime_loader/elf_symbol_lookup.cpp b/src/system/runtime_loader/elf_symbol_lookup.cpp index b2f6d16a04..1983197dc2 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.cpp +++ b/src/system/runtime_loader/elf_symbol_lookup.cpp @@ -93,28 +93,28 @@ patch_undefined_symbol(image_t* rootImage, image_t* image, const char* name, } -Elf32_Sym* +elf_sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo) { if (image->dynamic_ptr == 0) return NULL; - Elf32_Sym* versionedSymbol = NULL; + elf_sym* versionedSymbol = NULL; uint32 versionedSymbolCount = 0; uint32 bucket = lookupInfo.hash % HASHTABSIZE(image); for (uint32 i = HASHBUCKETS(image)[bucket]; i != STN_UNDEF; i = HASHCHAINS(image)[i]) { - Elf32_Sym* symbol = &image->syms[i]; + elf_sym* symbol = &image->syms[i]; if (symbol->st_shndx != SHN_UNDEF - && ((ELF32_ST_BIND(symbol->st_info) == STB_GLOBAL) - || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK)) + && ((symbol->Bind() == STB_GLOBAL) + || (symbol->Bind() == STB_WEAK)) && !strcmp(SYMNAME(image, symbol), lookupInfo.name)) { // check if the type matches - uint32 type = ELF32_ST_TYPE(symbol->st_info); + uint32 type = symbol->Type(); if ((lookupInfo.type == B_SYMBOL_TYPE_TEXT && type != STT_FUNC) || (lookupInfo.type == B_SYMBOL_TYPE_DATA && type != STT_OBJECT)) { @@ -219,7 +219,7 @@ find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo, void **_location) { // get the symbol in the image - Elf32_Sym* symbol = find_symbol(image, lookupInfo); + elf_sym* symbol = find_symbol(image, lookupInfo); if (symbol == NULL) return B_ENTRY_NOT_FOUND; @@ -244,16 +244,16 @@ find_symbol_breadth_first(image_t* image, const SymbolLookupInfo& lookupInfo, queue[count++] = image; image->flags |= RFLAG_VISITED; - Elf32_Sym* candidateSymbol = NULL; + elf_sym* candidateSymbol = NULL; image_t* candidateImage = NULL; while (index < count) { // pop next image image = queue[index++]; - Elf32_Sym* symbol = find_symbol(image, lookupInfo); + elf_sym* symbol = find_symbol(image, lookupInfo); if (symbol != NULL) { - bool isWeak = ELF32_ST_BIND(symbol->st_info) == STB_WEAK; + bool isWeak = symbol->Bind() == STB_WEAK; if (candidateImage == NULL || !isWeak) { candidateSymbol = symbol; candidateImage = image; @@ -294,7 +294,7 @@ find_symbol_breadth_first(image_t* image, const SymbolLookupInfo& lookupInfo, } -Elf32_Sym* +elf_sym* find_undefined_symbol_beos(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** foundInImage) { @@ -303,17 +303,17 @@ find_undefined_symbol_beos(image_t* rootImage, image_t* image, // symbol wasn't there. First we check whether the requesting symbol is // defined already -- then we can simply return it, since, due to symbolic // linking, that's the one we'd find anyway. - if (Elf32_Sym* symbol = lookupInfo.requestingSymbol) { + if (elf_sym* symbol = lookupInfo.requestingSymbol) { if (symbol->st_shndx != SHN_UNDEF - && ((ELF32_ST_BIND(symbol->st_info) == STB_GLOBAL) - || (ELF32_ST_BIND(symbol->st_info) == STB_WEAK))) { + && ((symbol->Bind() == STB_GLOBAL) + || (symbol->Bind() == STB_WEAK))) { *foundInImage = image; return symbol; } } // lookup in image - Elf32_Sym* symbol = find_symbol(image, lookupInfo); + elf_sym* symbol = find_symbol(image, lookupInfo); if (symbol != NULL) { *foundInImage = image; return symbol; @@ -334,7 +334,7 @@ find_undefined_symbol_beos(image_t* rootImage, image_t* image, } -Elf32_Sym* +elf_sym* find_undefined_symbol_global(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** _foundInImage) { @@ -342,7 +342,7 @@ find_undefined_symbol_global(image_t* rootImage, image_t* image, // the symbol in the order they have been loaded. We skip add-on images and // RTLD_LOCAL images though. image_t* candidateImage = NULL; - Elf32_Sym* candidateSymbol = NULL; + elf_sym* candidateSymbol = NULL; // If the requesting image is linked symbolically, look up the symbol there // first. @@ -350,7 +350,7 @@ find_undefined_symbol_global(image_t* rootImage, image_t* image, if (symbolic) { candidateSymbol = find_symbol(image, lookupInfo); if (candidateSymbol != NULL) { - if (ELF32_ST_BIND(candidateSymbol->st_info) != STB_WEAK) { + if (candidateSymbol->Bind() != STB_WEAK) { *_foundInImage = image; return candidateSymbol; } @@ -366,8 +366,8 @@ find_undefined_symbol_global(image_t* rootImage, image_t* image, : (otherImage->type != B_ADD_ON_IMAGE && (otherImage->flags & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) != 0)) { - if (Elf32_Sym* symbol = find_symbol(otherImage, lookupInfo)) { - if (ELF32_ST_BIND(symbol->st_info) != STB_WEAK) { + if (elf_sym* symbol = find_symbol(otherImage, lookupInfo)) { + if (symbol->Bind() != STB_WEAK) { *_foundInImage = otherImage; return symbol; } @@ -388,7 +388,7 @@ find_undefined_symbol_global(image_t* rootImage, image_t* image, } -Elf32_Sym* +elf_sym* find_undefined_symbol_add_on(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** _foundInImage) { @@ -410,9 +410,9 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image, // weak symbols that must be resolved globally from those that should be // resolved within the add-on. if (rootImage == image) { - if (Elf32_Sym* symbol = lookupInfo.requestingSymbol) { + if (elf_sym* symbol = lookupInfo.requestingSymbol) { if (symbol->st_shndx != SHN_UNDEF - && (ELF32_ST_BIND(symbol->st_info) == STB_GLOBAL)) { + && (symbol->Bind() == STB_GLOBAL)) { *_foundInImage = image; return symbol; } @@ -420,7 +420,7 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image, } image_t* candidateImage = NULL; - Elf32_Sym* candidateSymbol = NULL; + elf_sym* candidateSymbol = NULL; // If the requesting image is linked symbolically, look up the symbol there // first. @@ -428,7 +428,7 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image, if (symbolic) { candidateSymbol = find_symbol(image, lookupInfo); if (candidateSymbol != NULL) { - if (ELF32_ST_BIND(candidateSymbol->st_info) != STB_WEAK) { + if (candidateSymbol->Bind() != STB_WEAK) { *_foundInImage = image; return candidateSymbol; } @@ -443,8 +443,8 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image, && otherImage->type != B_ADD_ON_IMAGE && (otherImage->flags & (RTLD_GLOBAL | RFLAG_USE_FOR_RESOLVING)) != 0) { - if (Elf32_Sym* symbol = find_symbol(otherImage, lookupInfo)) { - if (ELF32_ST_BIND(symbol->st_info) != STB_WEAK) { + if (elf_sym* symbol = find_symbol(otherImage, lookupInfo)) { + if (symbol->Bind() != STB_WEAK) { *_foundInImage = otherImage; return symbol; } @@ -473,7 +473,7 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image, int -resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, +resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym, SymbolLookupCache* cache, addr_t* symAddress) { uint32 index = sym - image->syms; @@ -484,18 +484,18 @@ resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, return B_OK; } - struct Elf32_Sym* sharedSym; + elf_sym* sharedSym; image_t* sharedImage; const char* symName = SYMNAME(image, sym); // get the symbol type int32 type = B_SYMBOL_TYPE_ANY; - if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC) + if (sym->Type() == STT_FUNC) type = B_SYMBOL_TYPE_TEXT; - else if (ELF32_ST_TYPE(sym->st_info) == STT_OBJECT) + else if (sym->Type() == STT_OBJECT) type = B_SYMBOL_TYPE_DATA; - if (ELF32_ST_BIND(sym->st_info) == STB_LOCAL) { + if (sym->Bind() == STB_LOCAL) { // Local symbols references are always resolved to the given symbol. sharedImage = image; sharedSym = sym; @@ -526,14 +526,13 @@ resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, // symbol not found at all lookupError = ERROR_NO_SYMBOL; sharedImage = NULL; - } else if (ELF32_ST_TYPE(sym->st_info) != STT_NOTYPE - && ELF32_ST_TYPE(sym->st_info) - != ELF32_ST_TYPE(sharedSym->st_info)) { + } else if (sym->Type() != STT_NOTYPE + && sym->Type() != sharedSym->Type()) { // symbol not of the requested type lookupError = ERROR_WRONG_TYPE; sharedImage = NULL; - } else if (ELF32_ST_BIND(sharedSym->st_info) != STB_GLOBAL - && ELF32_ST_BIND(sharedSym->st_info) != STB_WEAK) { + } else if (sharedSym->Bind() != STB_GLOBAL + && sharedSym->Bind() != STB_WEAK) { // symbol not exported lookupError = ERROR_NOT_EXPORTED; sharedImage = NULL; diff --git a/src/system/runtime_loader/elf_symbol_lookup.h b/src/system/runtime_loader/elf_symbol_lookup.h index 3f2791317f..5be9e542c7 100644 --- a/src/system/runtime_loader/elf_symbol_lookup.h +++ b/src/system/runtime_loader/elf_symbol_lookup.h @@ -25,11 +25,11 @@ struct SymbolLookupInfo { uint32 hash; uint32 flags; const elf_version_info* version; - Elf32_Sym* requestingSymbol; + elf_sym* requestingSymbol; SymbolLookupInfo(const char* name, int32 type, uint32 hash, const elf_version_info* version = NULL, uint32 flags = 0, - Elf32_Sym* requestingSymbol = NULL) + elf_sym* requestingSymbol = NULL) : name(name), type(type), @@ -42,7 +42,7 @@ struct SymbolLookupInfo { SymbolLookupInfo(const char* name, int32 type, const elf_version_info* version = NULL, uint32 flags = 0, - Elf32_Sym* requestingSymbol = NULL) + elf_sym* requestingSymbol = NULL) : name(name), type(type), @@ -115,17 +115,17 @@ void patch_undefined_symbol(image_t* rootImage, image_t* image, const char* name, image_t** foundInImage, void** symbol, int32* type); -Elf32_Sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo); +elf_sym* find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo); status_t find_symbol(image_t* image, const SymbolLookupInfo& lookupInfo, void** _location); status_t find_symbol_breadth_first(image_t* image, const SymbolLookupInfo& lookupInfo, image_t** _foundInImage, void** _location); -Elf32_Sym* find_undefined_symbol_beos(image_t* rootImage, image_t* image, +elf_sym* find_undefined_symbol_beos(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** foundInImage); -Elf32_Sym* find_undefined_symbol_global(image_t* rootImage, image_t* image, +elf_sym* find_undefined_symbol_global(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** foundInImage); -Elf32_Sym* find_undefined_symbol_add_on(image_t* rootImage, image_t* image, +elf_sym* find_undefined_symbol_add_on(image_t* rootImage, image_t* image, const SymbolLookupInfo& lookupInfo, image_t** foundInImage); diff --git a/src/system/runtime_loader/elf_versioning.cpp b/src/system/runtime_loader/elf_versioning.cpp index 756459aa68..9785d1d9f3 100644 --- a/src/system/runtime_loader/elf_versioning.cpp +++ b/src/system/runtime_loader/elf_versioning.cpp @@ -26,7 +26,7 @@ assert_defined_image_version(image_t* dependentImage, image_t* image, } // iterate through the defined versions to find the given one - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { uint32 versionIndex = VER_NDX(definition->vd_ndx); elf_version_info& info = image->versions[versionIndex]; @@ -36,8 +36,7 @@ assert_defined_image_version(image_t* dependentImage, image_t* image, return B_OK; } - definition = (Elf32_Verdef*) - ((uint8*)definition + definition->vd_next); + definition = (elf_verdef*)((uint8*)definition + definition->vd_next); } // version not found -- fail, if not weak @@ -63,7 +62,7 @@ init_image_version_infos(image_t* image) uint32 maxIndex = 0; if (image->version_definitions != NULL) { - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { if (definition->vd_version != 1) { FATAL("%s: Unsupported version definition revision: %u\n", @@ -75,13 +74,13 @@ init_image_version_infos(image_t* image) if (versionIndex > maxIndex) maxIndex = versionIndex; - definition = (Elf32_Verdef*) - ((uint8*)definition + definition->vd_next); + definition = (elf_verdef*) + ((uint8*)definition + definition->vd_next); } } if (image->needed_versions != NULL) { - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { if (needed->vn_version != 1) { FATAL("%s: Unsupported version needed revision: %u\n", @@ -89,17 +88,17 @@ init_image_version_infos(image_t* image) return B_BAD_VALUE; } - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); if (versionIndex > maxIndex) maxIndex = versionIndex; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } } @@ -119,12 +118,12 @@ init_image_version_infos(image_t* image) // version definitions if (image->version_definitions != NULL) { - Elf32_Verdef* definition = image->version_definitions; + elf_verdef* definition = image->version_definitions; for (uint32 i = 0; i < image->num_version_definitions; i++) { if (definition->vd_cnt > 0 && (definition->vd_flags & VER_FLG_BASE) == 0) { - Elf32_Verdaux* verdaux - = (Elf32_Verdaux*)((uint8*)definition + definition->vd_aux); + elf_verdaux* verdaux + = (elf_verdaux*)((uint8*)definition + definition->vd_aux); uint32 versionIndex = VER_NDX(definition->vd_ndx); elf_version_info& info = image->versions[versionIndex]; @@ -133,19 +132,19 @@ init_image_version_infos(image_t* image) info.file_name = NULL; } - definition = (Elf32_Verdef*) + definition = (elf_verdef*) ((uint8*)definition + definition->vd_next); } } // needed versions if (image->needed_versions != NULL) { - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { const char* fileName = STRING(image, needed->vn_file); - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); elf_version_info& info = image->versions[versionIndex]; @@ -153,10 +152,10 @@ init_image_version_infos(image_t* image) info.name = STRING(image, vernaux->vna_name); info.file_name = fileName; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } } @@ -170,7 +169,7 @@ check_needed_image_versions(image_t* image) if (image->needed_versions == NULL) return B_OK; - Elf32_Verneed* needed = image->needed_versions; + elf_verneed* needed = image->needed_versions; for (uint32 i = 0; i < image->num_needed_versions; i++) { const char* fileName = STRING(image, needed->vn_file); image_t* dependency = find_loaded_image_by_name(fileName, @@ -183,8 +182,8 @@ check_needed_image_versions(image_t* image) return B_FILE_NOT_FOUND; } - Elf32_Vernaux* vernaux - = (Elf32_Vernaux*)((uint8*)needed + needed->vn_aux); + elf_vernaux* vernaux + = (elf_vernaux*)((uint8*)needed + needed->vn_aux); for (uint32 k = 0; k < needed->vn_cnt; k++) { uint32 versionIndex = VER_NDX(vernaux->vna_other); elf_version_info& info = image->versions[versionIndex]; @@ -194,10 +193,10 @@ check_needed_image_versions(image_t* image) if (error != B_OK) return error; - vernaux = (Elf32_Vernaux*)((uint8*)vernaux + vernaux->vna_next); + vernaux = (elf_vernaux*)((uint8*)vernaux + vernaux->vna_next); } - needed = (Elf32_Verneed*)((uint8*)needed + needed->vn_next); + needed = (elf_verneed*)((uint8*)needed + needed->vn_next); } return B_OK; diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp index 0446b6d286..0f504a9335 100644 --- a/src/system/runtime_loader/images.cpp +++ b/src/system/runtime_loader/images.cpp @@ -50,7 +50,7 @@ update_image_id(image_t* image) } } - FATAL("Could not update image ID %ld after fork()!\n", image->id); + FATAL("Could not update image ID %" B_PRId32 " after fork()!\n", image->id); return B_ENTRY_NOT_FOUND; } @@ -330,7 +330,7 @@ map_image(int fd, char const* path, image_t* image, bool fixed) for (uint32 i = 0; i < image->num_regions; i++) { char regionName[B_OS_NAME_LENGTH]; - snprintf(regionName, sizeof(regionName), "%s_seg%lu%s", + snprintf(regionName, sizeof(regionName), "%s_seg%" B_PRIu32 "%s", baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); get_image_region_load_address(image, i, diff --git a/src/system/runtime_loader/runtime_loader.cpp b/src/system/runtime_loader/runtime_loader.cpp index bbc9c45f0a..3389103901 100644 --- a/src/system/runtime_loader/runtime_loader.cpp +++ b/src/system/runtime_loader/runtime_loader.cpp @@ -9,7 +9,6 @@ #include "runtime_loader_private.h" -#include #include #include @@ -348,7 +347,7 @@ test_executable(const char *name, char *invoker) status = B_OK; } } else if (status == B_OK) { - struct Elf32_Ehdr *elfHeader = (struct Elf32_Ehdr *)buffer; + elf_ehdr *elfHeader = (elf_ehdr *)buffer; if (elfHeader->e_entry == 0) { // we don't like to open shared libraries status = B_NOT_AN_EXECUTABLE; diff --git a/src/system/runtime_loader/runtime_loader_private.h b/src/system/runtime_loader/runtime_loader_private.h index 3ac2d0dfab..f3f6dd38e0 100644 --- a/src/system/runtime_loader/runtime_loader_private.h +++ b/src/system/runtime_loader/runtime_loader_private.h @@ -73,11 +73,11 @@ status_t get_library_symbol(void* handle, void* caller, const char* symbolName, void** _location); status_t get_next_image_dependency(image_id id, uint32* cookie, const char** _name); -int resolve_symbol(image_t* rootImage, image_t* image, struct Elf32_Sym* sym, +int resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym, SymbolLookupCache* cache, addr_t* sym_addr); -status_t elf_verify_header(void* header, int32 length); +status_t elf_verify_header(void* header, size_t length); void rldelf_init(void); void rldexport_init(void); status_t elf_reinit_after_fork(void); From 5f119ed78f400fbaec842d982fb7943a14d6b60e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 27 Jul 2012 09:22:54 +0100 Subject: [PATCH 131/273] Added x86_64 glue code. --- src/system/glue/arch/x86_64/Jamfile | 7 +++++ src/system/glue/arch/x86_64/crti.S | 43 +++++++++++++++++++++++++++++ src/system/glue/arch/x86_64/crtn.S | 27 ++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 src/system/glue/arch/x86_64/Jamfile create mode 100644 src/system/glue/arch/x86_64/crti.S create mode 100644 src/system/glue/arch/x86_64/crtn.S diff --git a/src/system/glue/arch/x86_64/Jamfile b/src/system/glue/arch/x86_64/Jamfile new file mode 100644 index 0000000000..4d43342366 --- /dev/null +++ b/src/system/glue/arch/x86_64/Jamfile @@ -0,0 +1,7 @@ +SubDir HAIKU_TOP src system glue arch x86_64 ; + +KernelObjects + crti.S + crtn.S + ; + diff --git a/src/system/glue/arch/x86_64/crti.S b/src/system/glue/arch/x86_64/crti.S new file mode 100644 index 0000000000..3ef8e5f8df --- /dev/null +++ b/src/system/glue/arch/x86_64/crti.S @@ -0,0 +1,43 @@ +/* + * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + + +/** This file contains the first part of the ".init" and ".fini" sections in + * the ELF executable. + * The functions defined here will be called during initialization/termination + * of the loaded executable/library. The ".init" and ".fini" sections are + * stacked together like this: + * + * crti.S entry point + * call to _init_before/_term_before + * crtbegin.S GCC specific: constructors/destructors are called, ... + * crtend.S + * crtn.S call to _init_after/_term_after + * exit + */ + + +.section .init +FUNCTION(_init): + push %rbp + movq %rsp, %rbp + + // Preserve image ID for call to __haiku_init_after. + push %rdi + + call __haiku_init_before + // crtbegin.o stuff comes here + +.section .fini +FUNCTION(_fini): + push %rbp + movq %rsp, %rbp + push %rdi + call __haiku_term_before + // crtend.o stuff comes here diff --git a/src/system/glue/arch/x86_64/crtn.S b/src/system/glue/arch/x86_64/crtn.S new file mode 100644 index 0000000000..8ed6433843 --- /dev/null +++ b/src/system/glue/arch/x86_64/crtn.S @@ -0,0 +1,27 @@ +/* + * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +/** This file contains the final part of the ".init" and ".fini" sections in + * the ELF executable. It is tightly connected to crti.S. + * Have a look at crti.S to find a description of what happens here. + */ + + +.section .init + // The image ID is preserved on the stack. + pop %rdi + call __haiku_init_after + movq %rbp, %rsp + pop %rbp + ret + +.section .fini + pop %rdi + call __haiku_term_after + movq %rbp, %rsp + pop %rbp + ret From 3fde53501d6fd13daa168378d3f8ae8f3ca6bafd Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 27 Jul 2012 15:21:41 +0100 Subject: [PATCH 132/273] Updated x86_64 fenv.h and added fenv.c. --- headers/posix/arch/x86_64/fenv.h | 13 +- headers/posix/arch/x86_64/fpu.h | 218 +++++++++++++++++++ headers/posix/fenv.h | 2 +- src/system/libroot/posix/arch/x86_64/Jamfile | 2 +- src/system/libroot/posix/arch/x86_64/fenv.c | 158 ++++++++++++++ 5 files changed, 386 insertions(+), 7 deletions(-) create mode 100644 headers/posix/arch/x86_64/fpu.h create mode 100644 src/system/libroot/posix/arch/x86_64/fenv.c diff --git a/headers/posix/arch/x86_64/fenv.h b/headers/posix/arch/x86_64/fenv.h index a9992f9fad..9a3df8eb9d 100644 --- a/headers/posix/arch/x86_64/fenv.h +++ b/headers/posix/arch/x86_64/fenv.h @@ -111,7 +111,8 @@ feclearexcept(int __excepts) static __inline int fegetexceptflag(fexcept_t *__flagp, int __excepts) { - int __mxcsr, __status; + uint32_t __mxcsr; + uint16_t __status; __stmxcsr(&__mxcsr); __fnstsw(&__status); @@ -125,7 +126,8 @@ int feraiseexcept(int __excepts); static __inline int fetestexcept(int __excepts) { - int __mxcsr, __status; + uint32_t __mxcsr; + uint16_t __status; __stmxcsr(&__mxcsr); __fnstsw(&__status); @@ -135,7 +137,7 @@ fetestexcept(int __excepts) static __inline int fegetround(void) { - int __control; + uint16_t __control; /* * We assume that the x87 and the SSE unit agree on the @@ -150,7 +152,8 @@ fegetround(void) static __inline int fesetround(int __round) { - int __mxcsr, __control; + uint32_t __mxcsr; + uint16_t __control; if (__round & ~_ROUND_MASK) return (-1); @@ -198,7 +201,7 @@ int fedisableexcept(int __mask); static __inline int fegetexcept(void) { - int __control; + uint16_t __control; /* * We assume that the masks for the x87 and the SSE unit are diff --git a/headers/posix/arch/x86_64/fpu.h b/headers/posix/arch/x86_64/fpu.h new file mode 100644 index 0000000000..a22d8ca1f8 --- /dev/null +++ b/headers/posix/arch/x86_64/fpu.h @@ -0,0 +1,218 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)npx.h 5.3 (Berkeley) 1/18/91 + * $FreeBSD$ + */ + +/* + * Floating Point Data Structures and Constants + * W. Jolitz 1/90 + */ + +#ifndef _X86_FPU_H_ +#define _X86_FPU_H_ + +#define __aligned(x) __attribute__((__aligned__(x))) + +/* Environment information of floating point unit. */ +struct env87 { + int32_t en_cw; /* control word (16bits) */ + int32_t en_sw; /* status word (16bits) */ + int32_t en_tw; /* tag word (16bits) */ + int32_t en_fip; /* fp instruction pointer */ + uint16_t en_fcs; /* fp code segment selector */ + uint16_t en_opcode; /* opcode last executed (11 bits) */ + int32_t en_foo; /* fp operand offset */ + int32_t en_fos; /* fp operand segment selector */ +}; + +/* Contents of each x87 floating point accumulator. */ +struct fpacc87 { + uint8_t fp_bytes[10]; +}; + +/* Floating point context. (i386 fnsave/frstor) */ +struct save87 { + struct env87 sv_env; /* floating point control/status */ + struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ + uint8_t sv_pad0[4]; /* saved status word (now unused) */ + /* + * Bogus padding for emulators. Emulators should use their own + * struct and arrange to store into this struct (ending here) + * before it is inspected for ptracing or for core dumps. Some + * emulators overwrite the whole struct. We have no good way of + * knowing how much padding to leave. Leave just enough for the + * GPL emulator's i387_union (176 bytes total). + */ + uint8_t sv_pad[64]; /* padding; used by emulators */ +}; + +/* Contents of each SSE extended accumulator. */ +struct xmmacc { + uint8_t xmm_bytes[16]; +}; + +/* Contents of the upper 16 bytes of each AVX extended accumulator. */ +struct ymmacc { + uint8_t ymm_bytes[16]; +}; + +/* Rename structs below depending on machine architecture. */ +#ifdef __i386__ +#define __envxmm32 envxmm +#else +#define __envxmm32 envxmm32 +#define __envxmm64 envxmm +#endif + +struct __envxmm32 { + uint16_t en_cw; /* control word (16bits) */ + uint16_t en_sw; /* status word (16bits) */ + uint16_t en_tw; /* tag word (16bits) */ + uint16_t en_opcode; /* opcode last executed (11 bits) */ + uint32_t en_fip; /* fp instruction pointer */ + uint16_t en_fcs; /* fp code segment selector */ + uint16_t en_pad0; /* padding */ + uint32_t en_foo; /* fp operand offset */ + uint16_t en_fos; /* fp operand segment selector */ + uint16_t en_pad1; /* padding */ + uint32_t en_mxcsr; /* SSE control/status register */ + uint32_t en_mxcsr_mask; /* valid bits in mxcsr */ +}; + +struct __envxmm64 { + uint16_t en_cw; /* control word (16bits) */ + uint16_t en_sw; /* status word (16bits) */ + uint8_t en_tw; /* tag word (8bits) */ + uint8_t en_zero; + uint16_t en_opcode; /* opcode last executed (11 bits ) */ + uint64_t en_rip; /* fp instruction pointer */ + uint64_t en_rdp; /* fp operand pointer */ + uint32_t en_mxcsr; /* SSE control/status register */ + uint32_t en_mxcsr_mask; /* valid bits in mxcsr */ +}; + +/* Floating point context. (i386 fxsave/fxrstor) */ +struct savexmm { + struct __envxmm32 sv_env; + struct { + struct fpacc87 fp_acc; + uint8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[8]; + uint8_t sv_pad[224]; +} __aligned(16); + +#ifdef __i386__ +union savefpu { + struct save87 sv_87; + struct savexmm sv_xmm; +}; +#else +/* Floating point context. (amd64 fxsave/fxrstor) */ +struct savefpu { + struct __envxmm64 sv_env; + struct { + struct fpacc87 fp_acc; + uint8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; +} __aligned(16); +#endif + +struct xstate_hdr { + uint64_t xstate_bv; + uint8_t xstate_rsrv0[16]; + uint8_t xstate_rsrv[40]; +}; + +struct savexmm_xstate { + struct xstate_hdr sx_hd; + struct ymmacc sx_ymm[16]; +}; + +struct savexmm_ymm { + struct __envxmm32 sv_env; + struct { + struct fpacc87 fp_acc; + int8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; + struct savexmm_xstate sv_xstate; +} __aligned(64); + +struct savefpu_xstate { + struct xstate_hdr sx_hd; + struct ymmacc sx_ymm[16]; +}; + +struct savefpu_ymm { + struct __envxmm64 sv_env; + struct { + struct fpacc87 fp_acc; + int8_t fp_pad[6]; /* padding */ + } sv_fp[8]; + struct xmmacc sv_xmm[16]; + uint8_t sv_pad[96]; + struct savefpu_xstate sv_xstate; +} __aligned(64); + +#undef __envxmm32 +#undef __envxmm64 + +/* + * The hardware default control word for i387's and later coprocessors is + * 0x37F, giving: + * + * round to nearest + * 64-bit precision + * all exceptions masked. + * + * FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc + * because of the difference between memory and fpu register stack arguments. + * If its using an intermediate fpu register, it has 80/64 bits to work + * with. If it uses memory, it has 64/53 bits to work with. However, + * gcc is aware of this and goes to a fair bit of trouble to make the + * best use of it. + * + * This is mostly academic for AMD64, because the ABI prefers the use + * SSE2 based math. For FreeBSD/amd64, we go with the default settings. + */ +#define __INITIAL_FPUCW__ 0x037F +#define __INITIAL_FPUCW_I386__ 0x127F +#define __INITIAL_NPXCW__ __INITIAL_FPUCW_I386__ +#define __INITIAL_MXCSR__ 0x1F80 +#define __INITIAL_MXCSR_MASK__ 0xFFBF + +#endif /* !_X86_FPU_H_ */ diff --git a/headers/posix/fenv.h b/headers/posix/fenv.h index 0fb1e203c9..31fdd0b851 100644 --- a/headers/posix/fenv.h +++ b/headers/posix/fenv.h @@ -3,7 +3,7 @@ #if defined(__INTEL__) # include -#elif defined(_x86_64_) +#elif defined(__x86_64__) # include #elif defined(__ARM__) # include diff --git a/src/system/libroot/posix/arch/x86_64/Jamfile b/src/system/libroot/posix/arch/x86_64/Jamfile index cbbe85108d..5891f1b3e5 100644 --- a/src/system/libroot/posix/arch/x86_64/Jamfile +++ b/src/system/libroot/posix/arch/x86_64/Jamfile @@ -8,7 +8,7 @@ local genericSources = ; MergeObject posix_arch_$(TARGET_ARCH).o : - #fenv.c + fenv.c sigsetjmp.S siglongjmp.S diff --git a/src/system/libroot/posix/arch/x86_64/fenv.c b/src/system/libroot/posix/arch/x86_64/fenv.c new file mode 100644 index 0000000000..861f6217a9 --- /dev/null +++ b/src/system/libroot/posix/arch/x86_64/fenv.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2004-2005 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include + +const fenv_t __fe_dfl_env = { + { 0xffff0000 | __INITIAL_FPUCW__, + 0xffff0000, + 0xffffffff, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } + }, + __INITIAL_MXCSR__ +}; + +extern inline int feclearexcept(int __excepts); +extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); + +int +fesetexceptflag(const fexcept_t *flagp, int excepts) +{ + fenv_t env; + + __fnstenv(&env.__x87); + env.__x87.__status &= ~excepts; + env.__x87.__status |= *flagp & excepts; + __fldenv(env.__x87); + + __stmxcsr(&env.__mxcsr); + env.__mxcsr &= ~excepts; + env.__mxcsr |= *flagp & excepts; + __ldmxcsr(env.__mxcsr); + + return (0); +} + +int +feraiseexcept(int excepts) +{ + fexcept_t ex = excepts; + + fesetexceptflag(&ex, excepts); + __fwait(); + return (0); +} + +extern inline int fetestexcept(int __excepts); +extern inline int fegetround(void); +extern inline int fesetround(int __round); + +int +fegetenv(fenv_t *envp) +{ + + __fnstenv(&envp->__x87); + __stmxcsr(&envp->__mxcsr); + /* + * fnstenv masks all exceptions, so we need to restore the + * control word to avoid this side effect. + */ + __fldcw(envp->__x87.__control); + return (0); +} + +int +feholdexcept(fenv_t *envp) +{ + uint32_t mxcsr; + + __stmxcsr(&mxcsr); + __fnstenv(&envp->__x87); + __fnclex(); + envp->__mxcsr = mxcsr; + mxcsr &= ~FE_ALL_EXCEPT; + mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; + __ldmxcsr(mxcsr); + return (0); +} + +extern inline int fesetenv(const fenv_t *__envp); + +int +feupdateenv(const fenv_t *envp) +{ + uint32_t mxcsr; + uint16_t status; + + __fnstsw(&status); + __stmxcsr(&mxcsr); + fesetenv(envp); + feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); + return (0); +} + +int +__feenableexcept(int mask) +{ + uint32_t mxcsr, omask; + uint16_t control; + + mask &= FE_ALL_EXCEPT; + __fnstcw(&control); + __stmxcsr(&mxcsr); + omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + control &= ~mask; + __fldcw(control); + mxcsr &= ~(mask << _SSE_EMASK_SHIFT); + __ldmxcsr(mxcsr); + return (omask); +} + +int +__fedisableexcept(int mask) +{ + uint32_t mxcsr, omask; + uint16_t control; + + mask &= FE_ALL_EXCEPT; + __fnstcw(&control); + __stmxcsr(&mxcsr); + omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; + control |= mask; + __fldcw(control); + mxcsr |= mask << _SSE_EMASK_SHIFT; + __ldmxcsr(mxcsr); + return (omask); +} + +__weak_reference(__feenableexcept, feenableexcept); +__weak_reference(__fedisableexcept, fedisableexcept); From 04c1e6d01744fb03ca322b42d70dc731c049afe4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 27 Jul 2012 18:15:28 +0100 Subject: [PATCH 133/273] ASM code fixes for PIC compilation. --- src/system/libroot/os/arch/x86_64/system_time_asm.S | 8 ++++---- src/system/libroot/posix/arch/x86_64/siglongjmp.S | 2 +- src/system/libroot/posix/arch/x86_64/sigsetjmp.S | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/system/libroot/os/arch/x86_64/system_time_asm.S b/src/system/libroot/os/arch/x86_64/system_time_asm.S index 641c86de26..6af491a36d 100644 --- a/src/system/libroot/os/arch/x86_64/system_time_asm.S +++ b/src/system/libroot/os/arch/x86_64/system_time_asm.S @@ -20,8 +20,8 @@ FUNCTION(__x86_setup_system_time): - movq %rdi, cv_factor - movq %rsi, cv_factor_nsecs + movq %rdi, cv_factor(%rip) + movq %rsi, cv_factor_nsecs(%rip) ret FUNCTION_END(__x86_setup_system_time) @@ -31,7 +31,7 @@ FUNCTION(system_time): // (rdtsc * cv_factor) >> 32. // Factor is pre-shifted left by 32 bits. - movq cv_factor, %rcx + movq cv_factor(%rip), %rcx // Load 64-bit TSC into %eax (low), %edx (high). rdtsc @@ -56,7 +56,7 @@ FUNCTION(system_time_nsecs): // Factor has not been pre-shifted here, otherwise we may lose the upper // 32 bits. - movq cv_factor_nsecs, %rcx + movq cv_factor_nsecs(%rip), %rcx // Load 64-bit TSC into %eax (low), %edx (high). rdtsc diff --git a/src/system/libroot/posix/arch/x86_64/siglongjmp.S b/src/system/libroot/posix/arch/x86_64/siglongjmp.S index 5acae0990f..c42f7adb11 100644 --- a/src/system/libroot/posix/arch/x86_64/siglongjmp.S +++ b/src/system/libroot/posix/arch/x86_64/siglongjmp.S @@ -24,7 +24,7 @@ FUNCTION(_longjmp): push %rax // __longjmp_return restores the signal mask and sets the return value. - call __longjmp_return + call __longjmp_return@PLT ret FUNCTION_END(siglongjmp) diff --git a/src/system/libroot/posix/arch/x86_64/sigsetjmp.S b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S index 0e7b5afc77..70866974dc 100644 --- a/src/system/libroot/posix/arch/x86_64/sigsetjmp.S +++ b/src/system/libroot/posix/arch/x86_64/sigsetjmp.S @@ -24,7 +24,7 @@ FUNCTION(sigsetjmp): movq %r15, JMP_REGS_R15(%rdi) // __setjmp_save_sigs handles signal mask and return value. - jmp __setjmp_save_sigs + jmp __setjmp_save_sigs@PLT FUNCTION_END(setjmp) @@ -32,7 +32,7 @@ FUNCTION_END(setjmp) FUNCTION(setjmp): // Jump to sigsetjmp with a zero saveMask. xorl %esi, %esi - jmp sigsetjmp + jmp sigsetjmp@PLT FUNCTION_END(setjmp) From a3210bbc769a6b62188759cd4d3fd6b1114b1682 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 28 Jul 2012 12:23:47 +0100 Subject: [PATCH 134/273] Added x86_64 math functions to libroot. These have been pulled from glibc 2.10, the last version before a bunch of changes were made that would have made porting more difficult. None of this has been tested yet, it is not currently possible to do so: I'm just trying to get libroot compiling so that I can work on the runtime loader. I will test them when I am able to. --- src/system/libroot/posix/arch/x86_64/fenv.c | 9 - .../posix/glibc/arch/generic/e_atanhl.c | 79 ++ .../libroot/posix/glibc/arch/generic/e_j0l.c | 644 ++++++++++++ .../libroot/posix/glibc/arch/generic/e_j1l.c | 651 ++++++++++++ .../libroot/posix/glibc/arch/generic/e_jnl.c | 386 +++++++ .../posix/glibc/arch/generic/e_rem_pio2.c | 183 ++++ .../posix/glibc/arch/generic/s_asinhl.c | 70 ++ .../posix/glibc/arch/generic/s_cbrtl.c | 71 ++ .../libroot/posix/glibc/arch/generic/s_fdim.c | 40 + .../posix/glibc/arch/generic/s_fdimf.c | 36 + .../posix/glibc/arch/generic/s_frexpl.c | 70 ++ .../posix/glibc/arch/generic/s_ldexpl.c | 37 + .../posix/glibc/arch/generic/s_nearbyint.c | 105 ++ .../posix/glibc/arch/generic/s_nearbyintf.c | 77 ++ .../libroot/posix/glibc/arch/generic/s_rint.c | 98 ++ .../posix/glibc/arch/generic/s_rintf.c | 72 ++ .../posix/glibc/arch/generic/s_scalbln.c | 70 ++ .../posix/glibc/arch/generic/s_scalblnf.c | 63 ++ .../posix/glibc/arch/generic/s_scalblnl.c | 71 ++ .../posix/glibc/arch/generic/s_tanhl.c | 95 ++ .../libroot/posix/glibc/arch/generic/t_exp2.h | 585 +++++++++++ .../posix/glibc/arch/generic/t_exp2f.h | 352 +++++++ .../libroot/posix/glibc/arch/x86_64/Jamfile | 136 +++ .../libroot/posix/glibc/arch/x86_64/add_n.S | 42 + .../posix/glibc/arch/x86_64/addmul_1.S | 46 + .../libroot/posix/glibc/arch/x86_64/e_acosl.c | 25 + .../posix/glibc/arch/x86_64/e_atan2l.c | 18 + .../libroot/posix/glibc/arch/x86_64/e_exp2l.S | 38 + .../libroot/posix/glibc/arch/x86_64/e_expl.c | 77 ++ .../libroot/posix/glibc/arch/x86_64/e_fmodl.S | 22 + .../posix/glibc/arch/x86_64/e_log10l.S | 67 ++ .../libroot/posix/glibc/arch/x86_64/e_log2l.S | 64 ++ .../libroot/posix/glibc/arch/x86_64/e_logl.S | 66 ++ .../libroot/posix/glibc/arch/x86_64/e_powl.S | 341 ++++++ .../posix/glibc/arch/x86_64/e_rem_pio2l.c | 3 + .../posix/glibc/arch/x86_64/e_remainderl.S | 20 + .../posix/glibc/arch/x86_64/e_scalbl.S | 100 ++ .../libroot/posix/glibc/arch/x86_64/e_sqrt.c | 30 + .../libroot/posix/glibc/arch/x86_64/e_sqrtf.c | 30 + .../libroot/posix/glibc/arch/x86_64/e_sqrtl.c | 18 + .../posix/glibc/arch/x86_64/fegetround.c | 33 + .../posix/glibc/arch/x86_64/fesetenv.c | 89 ++ .../posix/glibc/arch/x86_64/fesetround.c | 47 + .../libroot/posix/glibc/arch/x86_64/k_cosl.c | 1 + .../posix/glibc/arch/x86_64/k_rem_pio2l.c | 1 + .../libroot/posix/glibc/arch/x86_64/k_sinl.c | 1 + .../libroot/posix/glibc/arch/x86_64/k_tanl.c | 1 + .../posix/glibc/arch/x86_64/ldbl2mpn.c | 1 + .../libroot/posix/glibc/arch/x86_64/lshift.S | 60 ++ .../posix/glibc/arch/x86_64/math_private.h | 21 + .../libroot/posix/glibc/arch/x86_64/mul_1.S | 42 + .../libroot/posix/glibc/arch/x86_64/rshift.S | 62 ++ .../libroot/posix/glibc/arch/x86_64/s_atanl.c | 22 + .../libroot/posix/glibc/arch/x86_64/s_ceill.S | 31 + .../posix/glibc/arch/x86_64/s_copysign.S | 55 + .../posix/glibc/arch/x86_64/s_copysignf.S | 50 + .../posix/glibc/arch/x86_64/s_copysignl.S | 22 + .../libroot/posix/glibc/arch/x86_64/s_cosl.S | 40 + .../posix/glibc/arch/x86_64/s_expm1l.S | 89 ++ .../libroot/posix/glibc/arch/x86_64/s_fabs.c | 27 + .../libroot/posix/glibc/arch/x86_64/s_fabsf.c | 27 + .../libroot/posix/glibc/arch/x86_64/s_fabsl.S | 28 + .../libroot/posix/glibc/arch/x86_64/s_fdiml.S | 44 + .../posix/glibc/arch/x86_64/s_finitel.S | 16 + .../posix/glibc/arch/x86_64/s_floorl.S | 30 + .../libroot/posix/glibc/arch/x86_64/s_fmax.S | 36 + .../libroot/posix/glibc/arch/x86_64/s_fmaxf.S | 36 + .../libroot/posix/glibc/arch/x86_64/s_fmaxl.S | 40 + .../libroot/posix/glibc/arch/x86_64/s_fmin.S | 36 + .../libroot/posix/glibc/arch/x86_64/s_fminf.S | 36 + .../libroot/posix/glibc/arch/x86_64/s_fminl.S | 38 + .../posix/glibc/arch/x86_64/s_fpclassifyl.c | 43 + .../posix/glibc/arch/x86_64/s_ilogbl.S | 35 + .../posix/glibc/arch/x86_64/s_isinfl.c | 37 + .../posix/glibc/arch/x86_64/s_isnanl.c | 48 + .../posix/glibc/arch/x86_64/s_llrint.S | 31 + .../posix/glibc/arch/x86_64/s_llrintf.S | 31 + .../posix/glibc/arch/x86_64/s_llrintl.S | 34 + .../posix/glibc/arch/x86_64/s_log1pl.S | 72 ++ .../libroot/posix/glibc/arch/x86_64/s_logbl.c | 19 + .../libroot/posix/glibc/arch/x86_64/s_lrint.S | 1 + .../posix/glibc/arch/x86_64/s_lrintf.S | 1 + .../posix/glibc/arch/x86_64/s_lrintl.S | 1 + .../posix/glibc/arch/x86_64/s_nearbyintl.S | 21 + .../posix/glibc/arch/x86_64/s_nextafterl.c | 124 +++ .../posix/glibc/arch/x86_64/s_nexttoward.c | 107 ++ .../posix/glibc/arch/x86_64/s_nexttowardf.c | 87 ++ .../libroot/posix/glibc/arch/x86_64/s_rintl.c | 18 + .../posix/glibc/arch/x86_64/s_scalbnl.S | 18 + .../posix/glibc/arch/x86_64/s_significandl.c | 19 + .../posix/glibc/arch/x86_64/s_sincos.S | 61 ++ .../posix/glibc/arch/x86_64/s_sincosl.S | 60 ++ .../libroot/posix/glibc/arch/x86_64/s_sinl.S | 40 + .../libroot/posix/glibc/arch/x86_64/s_tanl.S | 43 + .../posix/glibc/arch/x86_64/s_truncl.S | 34 + .../libroot/posix/glibc/arch/x86_64/sub_n.S | 42 + .../posix/glibc/arch/x86_64/submul_1.S | 46 + .../glibc/include/arch/x86_64/asm-syntax.h | 24 + .../glibc/include/arch/x86_64/bits/byteswap.h | 133 +++ .../glibc/include/arch/x86_64/bits/endian.h | 7 + .../glibc/include/arch/x86_64/bits/fenv.h | 93 ++ .../include/arch/x86_64/bits/fenvinline.h | 8 + .../glibc/include/arch/x86_64/bits/huge_val.h | 40 + .../glibc/include/arch/x86_64/bits/mathdef.h | 57 + .../include/arch/x86_64/bits/mathinline.h | 970 ++++++++++++++++++ .../glibc/include/arch/x86_64/bits/nan.h | 52 + .../glibc/include/arch/x86_64/bits/wordsize.h | 8 + .../posix/glibc/include/arch/x86_64/bp-asm.h | 141 +++ .../posix/glibc/include/arch/x86_64/config.h | 235 +++++ .../glibc/include/arch/x86_64/math_ldbl.h | 79 ++ .../glibc/include/arch/x86_64/stackinfo.h | 28 + .../posix/glibc/include/arch/x86_64/sysdep.h | 131 +++ 112 files changed, 9139 insertions(+), 9 deletions(-) create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_atanhl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_j0l.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_j1l.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_jnl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/e_rem_pio2.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_asinhl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_cbrtl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_fdim.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_fdimf.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_frexpl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_ldexpl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_nearbyint.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_nearbyintf.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_rint.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_rintf.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_scalbln.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_scalblnf.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_scalblnl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/s_tanhl.c create mode 100644 src/system/libroot/posix/glibc/arch/generic/t_exp2.h create mode 100644 src/system/libroot/posix/glibc/arch/generic/t_exp2f.h create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/Jamfile create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/add_n.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/addmul_1.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_acosl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_atan2l.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_exp2l.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_expl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_fmodl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_log10l.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_log2l.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_logl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_powl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_rem_pio2l.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_remainderl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_scalbl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_sqrt.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_sqrtf.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/e_sqrtl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/fegetround.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/fesetenv.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/fesetround.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/k_cosl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/k_rem_pio2l.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/k_sinl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/k_tanl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/ldbl2mpn.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/lshift.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/math_private.h create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/mul_1.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/rshift.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_atanl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_ceill.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_copysign.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_copysignf.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_copysignl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_cosl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_expm1l.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fabs.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fabsf.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fabsl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fdiml.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_finitel.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_floorl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fmax.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fmaxf.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fmaxl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fmin.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fminf.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fminl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_fpclassifyl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_ilogbl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_isinfl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_isnanl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_llrint.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_llrintf.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_llrintl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_log1pl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_logbl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_lrint.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_lrintf.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_lrintl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_nearbyintl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_nextafterl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_nexttoward.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_nexttowardf.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_rintl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_scalbnl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_significandl.c create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_sincos.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_sincosl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_sinl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_tanl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/s_truncl.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/sub_n.S create mode 100644 src/system/libroot/posix/glibc/arch/x86_64/submul_1.S create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/asm-syntax.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/byteswap.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/endian.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenv.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenvinline.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/huge_val.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathdef.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathinline.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/nan.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bits/wordsize.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/bp-asm.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/config.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/math_ldbl.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/stackinfo.h create mode 100644 src/system/libroot/posix/glibc/include/arch/x86_64/sysdep.h diff --git a/src/system/libroot/posix/arch/x86_64/fenv.c b/src/system/libroot/posix/arch/x86_64/fenv.c index 861f6217a9..d342453cee 100644 --- a/src/system/libroot/posix/arch/x86_64/fenv.c +++ b/src/system/libroot/posix/arch/x86_64/fenv.c @@ -41,9 +41,6 @@ const fenv_t __fe_dfl_env = { __INITIAL_MXCSR__ }; -extern inline int feclearexcept(int __excepts); -extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); - int fesetexceptflag(const fexcept_t *flagp, int excepts) { @@ -72,10 +69,6 @@ feraiseexcept(int excepts) return (0); } -extern inline int fetestexcept(int __excepts); -extern inline int fegetround(void); -extern inline int fesetround(int __round); - int fegetenv(fenv_t *envp) { @@ -105,8 +98,6 @@ feholdexcept(fenv_t *envp) return (0); } -extern inline int fesetenv(const fenv_t *__envp); - int feupdateenv(const fenv_t *envp) { diff --git a/src/system/libroot/posix/glibc/arch/generic/e_atanhl.c b/src/system/libroot/posix/glibc/arch/generic/e_atanhl.c new file mode 100644 index 0000000000..fdcd1e9fe8 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_atanhl.c @@ -0,0 +1,79 @@ +/* s_atanhl.c -- long double version of s_atan.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* __ieee754_atanhl(x) + * Method : + * 1.Reduced x to positive by atanh(-x) = -atanh(x) + * 2.For x>=0.5 + * 1 2x x + * atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) + * 2 1 - x 1 - x + * + * For x<0.5 + * atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x)) + * + * Special cases: + * atanhl(x) is NaN if |x| > 1 with signal; + * atanhl(NaN) is that NaN with no signal; + * atanhl(+-1) is +-INF with signal. + * + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double one = 1.0, huge = 1e4900L; +#else +static long double one = 1.0, huge = 1e4900L; +#endif + +#ifdef __STDC__ +static const long double zero = 0.0; +#else +static double long zero = 0.0; +#endif + +#ifdef __STDC__ + long double __ieee754_atanhl(long double x) +#else + long double __ieee754_atanhl(x) + long double x; +#endif +{ + long double t; + int32_t ix; + u_int32_t se,i0,i1; + GET_LDOUBLE_WORDS(se,i0,i1,x); + ix = se&0x7fff; + if ((ix+((((i0&0x7fffffff)|i1)|(-((i0&0x7fffffff)|i1)))>>31))>0x3fff) + /* |x|>1 */ + return (x-x)/(x-x); + if(ix==0x3fff) + return x/zero; + if(ix<0x3fe3&&(huge+x)>zero) return x; /* x<2**-28 */ + SET_LDOUBLE_EXP(x,ix); + if(ix<0x3ffe) { /* x < 0.5 */ + t = x+x; + t = 0.5*__log1pl(t+t*x/(one-x)); + } else + t = 0.5*__log1pl((x+x)/(one-x)); + if(se<=0x7fff) return t; else return -t; +} diff --git a/src/system/libroot/posix/glibc/arch/generic/e_j0l.c b/src/system/libroot/posix/glibc/arch/generic/e_j0l.c new file mode 100644 index 0000000000..12c906bcbc --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_j0l.c @@ -0,0 +1,644 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* Long double expansions are + Copyright (C) 2001 Stephen L. Moshier + and are incorporated herein by permission of the author. The author + reserves the right to distribute this material elsewhere under different + copying permissions. These modifications are distributed here under + the following terms: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* __ieee754_j0(x), __ieee754_y0(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1 - z/4 + z^2*R0/S0, where z = x*x; + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static long double pzero (long double), qzero (long double); +#else +static long double pzero (), qzero (); +#endif + +#ifdef __STDC__ +static const long double +#else +static long double +#endif + huge = 1e4930L, + one = 1.0L, + invsqrtpi = 5.6418958354775628694807945156077258584405e-1L, + tpi = 6.3661977236758134307553505349005744813784e-1L, + + /* J0(x) = 1 - x^2 / 4 + x^4 R0(x^2) / S0(x^2) + 0 <= x <= 2 + peak relative error 1.41e-22 */ + R[5] = { + 4.287176872744686992880841716723478740566E7L, + -6.652058897474241627570911531740907185772E5L, + 7.011848381719789863458364584613651091175E3L, + -3.168040850193372408702135490809516253693E1L, + 6.030778552661102450545394348845599300939E-2L, +}, + + S[4] = { + 2.743793198556599677955266341699130654342E9L, + 3.364330079384816249840086842058954076201E7L, + 1.924119649412510777584684927494642526573E5L, + 6.239282256012734914211715620088714856494E2L, + /* 1.000000000000000000000000000000000000000E0L,*/ +}; + +#ifdef __STDC__ +static const long double zero = 0.0; +#else +static long double zero = 0.0; +#endif + +#ifdef __STDC__ +long double +__ieee754_j0l (long double x) +#else +long double +__ieee754_j0l (x) + long double x; +#endif +{ + long double z, s, c, ss, cc, r, u, v; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x7fff) + return one / (x * x); + x = fabsl (x); + if (ix >= 0x4000) /* |x| >= 2.0 */ + { + __sincosl (x, &s, &c); + ss = s - c; + cc = s + c; + if (ix < 0x7ffe) + { /* make sure x+x not overflow */ + z = -__cosl (x + x); + if ((s * c) < zero) + cc = z / ss; + else + ss = z / cc; + } + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if (ix > 0x4080) /* 2^129 */ + z = (invsqrtpi * cc) / __ieee754_sqrtl (x); + else + { + u = pzero (x); + v = qzero (x); + z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrtl (x); + } + return z; + } + if (ix < 0x3fef) /* |x| < 2**-16 */ + { + if (huge + x > one) + { /* raise inexact if x != 0 */ + if (ix < 0x3fde) /* |x| < 2^-33 */ + return one; + else + return one - 0.25 * x * x; + } + } + z = x * x; + r = z * (R[0] + z * (R[1] + z * (R[2] + z * (R[3] + z * R[4])))); + s = S[0] + z * (S[1] + z * (S[2] + z * (S[3] + z))); + if (ix < 0x3fff) + { /* |x| < 1.00 */ + return (one - 0.25 * z + z * (r / s)); + } + else + { + u = 0.5 * x; + return ((one + u) * (one - u) + z * (r / s)); + } +} + + +/* y0(x) = 2/pi ln(x) J0(x) + U(x^2)/V(x^2) + 0 < x <= 2 + peak relative error 1.7e-21 */ +#ifdef __STDC__ +static const long double +#else +static long double +#endif +U[6] = { + -1.054912306975785573710813351985351350861E10L, + 2.520192609749295139432773849576523636127E10L, + -1.856426071075602001239955451329519093395E9L, + 4.079209129698891442683267466276785956784E7L, + -3.440684087134286610316661166492641011539E5L, + 1.005524356159130626192144663414848383774E3L, +}; +#ifdef __STDC__ +static const long double +#else +static long double +#endif +V[5] = { + 1.429337283720789610137291929228082613676E11L, + 2.492593075325119157558811370165695013002E9L, + 2.186077620785925464237324417623665138376E7L, + 1.238407896366385175196515057064384929222E5L, + 4.693924035211032457494368947123233101664E2L, + /* 1.000000000000000000000000000000000000000E0L */ +}; + +#ifdef __STDC__ +long double +__ieee754_y0l (long double x) +#else +long double +__ieee754_y0l (x) + long double x; +#endif +{ + long double z, s, c, ss, cc, u, v; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ + if (se & 0x8000) + return zero / (zero * x); + if (ix >= 0x7fff) + return one / (x + x * x); + if ((i0 | i1) == 0) + return -HUGE_VALL + x; /* -inf and overflow exception. */ + if (ix >= 0x4000) + { /* |x| >= 2.0 */ + + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + __sincosl (x, &s, &c); + ss = s - c; + cc = s + c; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if (ix < 0x7ffe) + { /* make sure x+x not overflow */ + z = -__cosl (x + x); + if ((s * c) < zero) + cc = z / ss; + else + ss = z / cc; + } + if (ix > 0x4080) /* 1e39 */ + z = (invsqrtpi * ss) / __ieee754_sqrtl (x); + else + { + u = pzero (x); + v = qzero (x); + z = invsqrtpi * (u * ss + v * cc) / __ieee754_sqrtl (x); + } + return z; + } + if (ix <= 0x3fde) /* x < 2^-33 */ + { + z = -7.380429510868722527629822444004602747322E-2L + + tpi * __ieee754_logl (x); + return z; + } + z = x * x; + u = U[0] + z * (U[1] + z * (U[2] + z * (U[3] + z * (U[4] + z * U[5])))); + v = V[0] + z * (V[1] + z * (V[2] + z * (V[3] + z * (V[4] + z)))); + return (u / v + tpi * (__ieee754_j0l (x) * __ieee754_logl (x))); +} + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + s^2 R(s^2) / S(s^2) + */ +#ifdef __STDC__ +static const long double pR8[7] = { +#else +static long double pR8[7] = { +#endif + /* 8 <= x <= inf + Peak relative error 4.62 */ + -4.094398895124198016684337960227780260127E-9L, + -8.929643669432412640061946338524096893089E-7L, + -6.281267456906136703868258380673108109256E-5L, + -1.736902783620362966354814353559382399665E-3L, + -1.831506216290984960532230842266070146847E-2L, + -5.827178869301452892963280214772398135283E-2L, + -2.087563267939546435460286895807046616992E-2L, +}; +#ifdef __STDC__ +static const long double pS8[6] = { +#else +static long double pS8[6] = { +#endif + 5.823145095287749230197031108839653988393E-8L, + 1.279281986035060320477759999428992730280E-5L, + 9.132668954726626677174825517150228961304E-4L, + 2.606019379433060585351880541545146252534E-2L, + 2.956262215119520464228467583516287175244E-1L, + 1.149498145388256448535563278632697465675E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double pR5[7] = { +#else +static long double pR5[7] = { +#endif + /* 4.54541015625 <= x <= 8 + Peak relative error 6.51E-22 */ + -2.041226787870240954326915847282179737987E-7L, + -2.255373879859413325570636768224534428156E-5L, + -7.957485746440825353553537274569102059990E-4L, + -1.093205102486816696940149222095559439425E-2L, + -5.657957849316537477657603125260701114646E-2L, + -8.641175552716402616180994954177818461588E-2L, + -1.354654710097134007437166939230619726157E-2L, +}; +#ifdef __STDC__ +static const long double pS5[6] = { +#else +static long double pS5[6] = { +#endif + 2.903078099681108697057258628212823545290E-6L, + 3.253948449946735405975737677123673867321E-4L, + 1.181269751723085006534147920481582279979E-2L, + 1.719212057790143888884745200257619469363E-1L, + 1.006306498779212467670654535430694221924E0L, + 2.069568808688074324555596301126375951502E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double pR3[7] = { +#else +static long double pR3[7] = { +#endif + /* 2.85711669921875 <= x <= 4.54541015625 + peak relative error 5.25e-21 */ + -5.755732156848468345557663552240816066802E-6L, + -3.703675625855715998827966962258113034767E-4L, + -7.390893350679637611641350096842846433236E-3L, + -5.571922144490038765024591058478043873253E-2L, + -1.531290690378157869291151002472627396088E-1L, + -1.193350853469302941921647487062620011042E-1L, + -8.567802507331578894302991505331963782905E-3L, +}; +#ifdef __STDC__ +static const long double pS3[6] = { +#else +static long double pS3[6] = { +#endif + 8.185931139070086158103309281525036712419E-5L, + 5.398016943778891093520574483111255476787E-3L, + 1.130589193590489566669164765853409621081E-1L, + 9.358652328786413274673192987670237145071E-1L, + 3.091711512598349056276917907005098085273E0L, + 3.594602474737921977972586821673124231111E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double pR2[7] = { +#else +static long double pR2[7] = { +#endif + /* 2 <= x <= 2.85711669921875 + peak relative error 2.64e-21 */ + -1.219525235804532014243621104365384992623E-4L, + -4.838597135805578919601088680065298763049E-3L, + -5.732223181683569266223306197751407418301E-2L, + -2.472947430526425064982909699406646503758E-1L, + -3.753373645974077960207588073975976327695E-1L, + -1.556241316844728872406672349347137975495E-1L, + -5.355423239526452209595316733635519506958E-3L, +}; +#ifdef __STDC__ +static const long double pS2[6] = { +#else +static long double pS2[6] = { +#endif + 1.734442793664291412489066256138894953823E-3L, + 7.158111826468626405416300895617986926008E-2L, + 9.153839713992138340197264669867993552641E-1L, + 4.539209519433011393525841956702487797582E0L, + 8.868932430625331650266067101752626253644E0L, + 6.067161890196324146320763844772857713502E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static long double +pzero (long double x) +#else +static long double +pzero (x) + long double x; +#endif +{ +#ifdef __STDC__ + const long double *p, *q; +#else + long double *p, *q; +#endif + long double z, r, s; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x4002) + { + p = pR8; + q = pS8; + } /* x >= 8 */ + else + { + i1 = (ix << 16) | (i0 >> 16); + if (i1 >= 0x40019174) /* x >= 4.54541015625 */ + { + p = pR5; + q = pS5; + } + else if (i1 >= 0x4000b6db) /* x >= 2.85711669921875 */ + { + p = pR3; + q = pS3; + } + else if (ix >= 0x4000) /* x better be >= 2 */ + { + p = pR2; + q = pS2; + } + } + z = one / (x * x); + r = + p[0] + z * (p[1] + + z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6]))))); + s = + q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * (q[5] + z))))); + return (one + z * r / s); +} + + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate qzero by + * qzero(x) = s*(-.125 + R(s^2) / S(s^2)) + */ +#ifdef __STDC__ +static const long double qR8[7] = { +#else +static long double qR8[7] = { +#endif + /* 8 <= x <= inf + peak relative error 2.23e-21 */ + 3.001267180483191397885272640777189348008E-10L, + 8.693186311430836495238494289942413810121E-8L, + 8.496875536711266039522937037850596580686E-6L, + 3.482702869915288984296602449543513958409E-4L, + 6.036378380706107692863811938221290851352E-3L, + 3.881970028476167836382607922840452192636E-2L, + 6.132191514516237371140841765561219149638E-2L, +}; +#ifdef __STDC__ +static const long double qS8[7] = { +#else +static long double qS8[7] = { +#endif + 4.097730123753051126914971174076227600212E-9L, + 1.199615869122646109596153392152131139306E-6L, + 1.196337580514532207793107149088168946451E-4L, + 5.099074440112045094341500497767181211104E-3L, + 9.577420799632372483249761659674764460583E-2L, + 7.385243015344292267061953461563695918646E-1L, + 1.917266424391428937962682301561699055943E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double qR5[7] = { +#else +static long double qR5[7] = { +#endif + /* 4.54541015625 <= x <= 8 + peak relative error 1.03e-21 */ + 3.406256556438974327309660241748106352137E-8L, + 4.855492710552705436943630087976121021980E-6L, + 2.301011739663737780613356017352912281980E-4L, + 4.500470249273129953870234803596619899226E-3L, + 3.651376459725695502726921248173637054828E-2L, + 1.071578819056574524416060138514508609805E-1L, + 7.458950172851611673015774675225656063757E-2L, +}; +#ifdef __STDC__ +static const long double qS5[7] = { +#else +static long double qS5[7] = { +#endif + 4.650675622764245276538207123618745150785E-7L, + 6.773573292521412265840260065635377164455E-5L, + 3.340711249876192721980146877577806687714E-3L, + 7.036218046856839214741678375536970613501E-2L, + 6.569599559163872573895171876511377891143E-1L, + 2.557525022583599204591036677199171155186E0L, + 3.457237396120935674982927714210361269133E0L, + /* 1.000000000000000000000000000000000000000E0L,*/ +}; + +#ifdef __STDC__ +static const long double qR3[7] = { +#else +static long double qR3[7] = { +#endif + /* 2.85711669921875 <= x <= 4.54541015625 + peak relative error 5.24e-21 */ + 1.749459596550816915639829017724249805242E-6L, + 1.446252487543383683621692672078376929437E-4L, + 3.842084087362410664036704812125005761859E-3L, + 4.066369994699462547896426554180954233581E-2L, + 1.721093619117980251295234795188992722447E-1L, + 2.538595333972857367655146949093055405072E-1L, + 8.560591367256769038905328596020118877936E-2L, +}; +#ifdef __STDC__ +static const long double qS3[7] = { +#else +static long double qS3[7] = { +#endif + 2.388596091707517488372313710647510488042E-5L, + 2.048679968058758616370095132104333998147E-3L, + 5.824663198201417760864458765259945181513E-2L, + 6.953906394693328750931617748038994763958E-1L, + 3.638186936390881159685868764832961092476E0L, + 7.900169524705757837298990558459547842607E0L, + 5.992718532451026507552820701127504582907E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double qR2[7] = { +#else +static long double qR2[7] = { +#endif + /* 2 <= x <= 2.85711669921875 + peak relative error 1.58e-21 */ + 6.306524405520048545426928892276696949540E-5L, + 3.209606155709930950935893996591576624054E-3L, + 5.027828775702022732912321378866797059604E-2L, + 3.012705561838718956481911477587757845163E-1L, + 6.960544893905752937420734884995688523815E-1L, + 5.431871999743531634887107835372232030655E-1L, + 9.447736151202905471899259026430157211949E-2L, +}; +#ifdef __STDC__ +static const long double qS2[7] = { +#else +static long double qS2[7] = { +#endif + 8.610579901936193494609755345106129102676E-4L, + 4.649054352710496997203474853066665869047E-2L, + 8.104282924459837407218042945106320388339E-1L, + 5.807730930825886427048038146088828206852E0L, + 1.795310145936848873627710102199881642939E1L, + 2.281313316875375733663657188888110605044E1L, + 1.011242067883822301487154844458322200143E1L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static long double +qzero (long double x) +#else +static long double +qzero (x) + long double x; +#endif +{ +#ifdef __STDC__ + const long double *p, *q; +#else + long double *p, *q; +#endif + long double s, r, z; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x4002) /* x >= 8 */ + { + p = qR8; + q = qS8; + } + else + { + i1 = (ix << 16) | (i0 >> 16); + if (i1 >= 0x40019174) /* x >= 4.54541015625 */ + { + p = qR5; + q = qS5; + } + else if (i1 >= 0x4000b6db) /* x >= 2.85711669921875 */ + { + p = qR3; + q = qS3; + } + else if (ix >= 0x4000) /* x better be >= 2 */ + { + p = qR2; + q = qS2; + } + } + z = one / (x * x); + r = + p[0] + z * (p[1] + + z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6]))))); + s = + q[0] + z * (q[1] + + z * (q[2] + + z * (q[3] + z * (q[4] + z * (q[5] + z * (q[6] + z)))))); + return (-.125 + z * r / s) / x; +} diff --git a/src/system/libroot/posix/glibc/arch/generic/e_j1l.c b/src/system/libroot/posix/glibc/arch/generic/e_j1l.c new file mode 100644 index 0000000000..62a8ce0cb7 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_j1l.c @@ -0,0 +1,651 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* Long double expansions are + Copyright (C) 2001 Stephen L. Moshier + and are incorporated herein by permission of the author. The author + reserves the right to distribute this material elsewhere under different + copying permissions. These modifications are distributed here under + the following terms: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* __ieee754_j1(x), __ieee754_y1(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follow: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static long double pone (long double), qone (long double); +#else +static long double pone (), qone (); +#endif + +#ifdef __STDC__ +static const long double +#else +static long double +#endif + huge = 1e4930L, + one = 1.0L, + invsqrtpi = 5.6418958354775628694807945156077258584405e-1L, + tpi = 6.3661977236758134307553505349005744813784e-1L, + + /* J1(x) = .5 x + x x^2 R(x^2) / S(x^2) + 0 <= x <= 2 + Peak relative error 4.5e-21 */ +R[5] = { + -9.647406112428107954753770469290757756814E7L, + 2.686288565865230690166454005558203955564E6L, + -3.689682683905671185891885948692283776081E4L, + 2.195031194229176602851429567792676658146E2L, + -5.124499848728030297902028238597308971319E-1L, +}, + + S[4] = +{ + 1.543584977988497274437410333029029035089E9L, + 2.133542369567701244002565983150952549520E7L, + 1.394077011298227346483732156167414670520E5L, + 5.252401789085732428842871556112108446506E2L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +#ifdef __STDC__ +static const long double zero = 0.0; +#else +static long double zero = 0.0; +#endif + + +#ifdef __STDC__ +long double +__ieee754_j1l (long double x) +#else +long double +__ieee754_j1l (x) + long double x; +#endif +{ + long double z, c, r, s, ss, cc, u, v, y; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x7fff) + return one / x; + y = fabsl (x); + if (ix >= 0x4000) + { /* |x| >= 2.0 */ + __sincosl (y, &s, &c); + ss = -s - c; + cc = s - c; + if (ix < 0x7ffe) + { /* make sure y+y not overflow */ + z = __cosl (y + y); + if ((s * c) > zero) + cc = z / ss; + else + ss = z / cc; + } + /* + * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) + * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) + */ + if (ix > 0x4080) + z = (invsqrtpi * cc) / __ieee754_sqrtl (y); + else + { + u = pone (y); + v = qone (y); + z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrtl (y); + } + if (se & 0x8000) + return -z; + else + return z; + } + if (ix < 0x3fde) /* |x| < 2^-33 */ + { + if (huge + x > one) + return 0.5 * x; /* inexact if x!=0 necessary */ + } + z = x * x; + r = z * (R[0] + z * (R[1]+ z * (R[2] + z * (R[3] + z * R[4])))); + s = S[0] + z * (S[1] + z * (S[2] + z * (S[3] + z))); + r *= x; + return (x * 0.5 + r / s); +} + + +/* Y1(x) = 2/pi * (log(x) * j1(x) - 1/x) + x R(x^2) + 0 <= x <= 2 + Peak relative error 2.3e-23 */ +#ifdef __STDC__ +static const long double U0[6] = { +#else +static long double U0[6] = { +#endif + -5.908077186259914699178903164682444848615E10L, + 1.546219327181478013495975514375773435962E10L, + -6.438303331169223128870035584107053228235E8L, + 9.708540045657182600665968063824819371216E6L, + -6.138043997084355564619377183564196265471E4L, + 1.418503228220927321096904291501161800215E2L, +}; +#ifdef __STDC__ +static const long double V0[5] = { +#else +static long double V0[5] = { +#endif + 3.013447341682896694781964795373783679861E11L, + 4.669546565705981649470005402243136124523E9L, + 3.595056091631351184676890179233695857260E7L, + 1.761554028569108722903944659933744317994E5L, + 5.668480419646516568875555062047234534863E2L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + + +#ifdef __STDC__ +long double +__ieee754_y1l (long double x) +#else +long double +__ieee754_y1l (x) + long double x; +#endif +{ + long double z, s, c, ss, cc, u, v; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ + if (se & 0x8000) + return zero / (zero * x); + if (ix >= 0x7fff) + return one / (x + x * x); + if ((i0 | i1) == 0) + return -HUGE_VALL + x; /* -inf and overflow exception. */ + if (ix >= 0x4000) + { /* |x| >= 2.0 */ + __sincosl (x, &s, &c); + ss = -s - c; + cc = s - c; + if (ix < 0x7fe00000) + { /* make sure x+x not overflow */ + z = __cosl (x + x); + if ((s * c) > zero) + cc = z / ss; + else + ss = z / cc; + } + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if (ix > 0x4080) + z = (invsqrtpi * ss) / __ieee754_sqrtl (x); + else + { + u = pone (x); + v = qone (x); + z = invsqrtpi * (u * ss + v * cc) / __ieee754_sqrtl (x); + } + return z; + } + if (ix <= 0x3fbe) + { /* x < 2**-65 */ + return (-tpi / x); + } + z = x * x; + u = U0[0] + z * (U0[1] + z * (U0[2] + z * (U0[3] + z * (U0[4] + z * U0[5])))); + v = V0[0] + z * (V0[1] + z * (V0[2] + z * (V0[3] + z * (V0[4] + z)))); + return (x * (u / v) + + tpi * (__ieee754_j1l (x) * __ieee754_logl (x) - one / x)); +} + + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + */ + +/* J1(x) cosX + Y1(x) sinX = sqrt( 2/(pi x)) P1(x) + P1(x) = 1 + z^2 R(z^2), z=1/x + 8 <= x <= inf (0 <= z <= 0.125) + Peak relative error 5.2e-22 */ + +#ifdef __STDC__ +static const long double pr8[7] = { +#else +static long double pr8[7] = { +#endif + 8.402048819032978959298664869941375143163E-9L, + 1.813743245316438056192649247507255996036E-6L, + 1.260704554112906152344932388588243836276E-4L, + 3.439294839869103014614229832700986965110E-3L, + 3.576910849712074184504430254290179501209E-2L, + 1.131111483254318243139953003461511308672E-1L, + 4.480715825681029711521286449131671880953E-2L, +}; +#ifdef __STDC__ +static const long double ps8[6] = { +#else +static long double ps8[6] = { +#endif + 7.169748325574809484893888315707824924354E-8L, + 1.556549720596672576431813934184403614817E-5L, + 1.094540125521337139209062035774174565882E-3L, + 3.060978962596642798560894375281428805840E-2L, + 3.374146536087205506032643098619414507024E-1L, + 1.253830208588979001991901126393231302559E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +/* J1(x) cosX + Y1(x) sinX = sqrt( 2/(pi x)) P1(x) + P1(x) = 1 + z^2 R(z^2), z=1/x + 4.54541015625 <= x <= 8 + Peak relative error 7.7e-22 */ +#ifdef __STDC__ +static const long double pr5[7] = { +#else +static long double pr5[7] = { +#endif + 4.318486887948814529950980396300969247900E-7L, + 4.715341880798817230333360497524173929315E-5L, + 1.642719430496086618401091544113220340094E-3L, + 2.228688005300803935928733750456396149104E-2L, + 1.142773760804150921573259605730018327162E-1L, + 1.755576530055079253910829652698703791957E-1L, + 3.218803858282095929559165965353784980613E-2L, +}; +#ifdef __STDC__ +static const long double ps5[6] = { +#else +static long double ps5[6] = { +#endif + 3.685108812227721334719884358034713967557E-6L, + 4.069102509511177498808856515005792027639E-4L, + 1.449728676496155025507893322405597039816E-2L, + 2.058869213229520086582695850441194363103E-1L, + 1.164890985918737148968424972072751066553E0L, + 2.274776933457009446573027260373361586841E0L, + /* 1.000000000000000000000000000000000000000E0L,*/ +}; + +/* J1(x) cosX + Y1(x) sinX = sqrt( 2/(pi x)) P1(x) + P1(x) = 1 + z^2 R(z^2), z=1/x + 2.85711669921875 <= x <= 4.54541015625 + Peak relative error 6.5e-21 */ +#ifdef __STDC__ +static const long double pr3[7] = { +#else +static long double pr3[7] = { +#endif + 1.265251153957366716825382654273326407972E-5L, + 8.031057269201324914127680782288352574567E-4L, + 1.581648121115028333661412169396282881035E-2L, + 1.179534658087796321928362981518645033967E-1L, + 3.227936912780465219246440724502790727866E-1L, + 2.559223765418386621748404398017602935764E-1L, + 2.277136933287817911091370397134882441046E-2L, +}; +#ifdef __STDC__ +static const long double ps3[6] = { +#else +static long double ps3[6] = { +#endif + 1.079681071833391818661952793568345057548E-4L, + 6.986017817100477138417481463810841529026E-3L, + 1.429403701146942509913198539100230540503E-1L, + 1.148392024337075609460312658938700765074E0L, + 3.643663015091248720208251490291968840882E0L, + 3.990702269032018282145100741746633960737E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +/* J1(x) cosX + Y1(x) sinX = sqrt( 2/(pi x)) P1(x) + P1(x) = 1 + z^2 R(z^2), z=1/x + 2 <= x <= 2.85711669921875 + Peak relative error 3.5e-21 */ +#ifdef __STDC__ +static const long double pr2[7] = { +#else +static long double pr2[7] = { +#endif + 2.795623248568412225239401141338714516445E-4L, + 1.092578168441856711925254839815430061135E-2L, + 1.278024620468953761154963591853679640560E-1L, + 5.469680473691500673112904286228351988583E-1L, + 8.313769490922351300461498619045639016059E-1L, + 3.544176317308370086415403567097130611468E-1L, + 1.604142674802373041247957048801599740644E-2L, +}; +#ifdef __STDC__ +static const long double ps2[6] = { +#else +static long double ps2[6] = { +#endif + 2.385605161555183386205027000675875235980E-3L, + 9.616778294482695283928617708206967248579E-2L, + 1.195215570959693572089824415393951258510E0L, + 5.718412857897054829999458736064922974662E0L, + 1.065626298505499086386584642761602177568E1L, + 6.809140730053382188468983548092322151791E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + + +#ifdef __STDC__ +static long double +pone (long double x) +#else +static long double +pone (x) + long double x; +#endif +{ +#ifdef __STDC__ + const long double *p, *q; +#else + long double *p, *q; +#endif + long double z, r, s; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x4002) /* x >= 8 */ + { + p = pr8; + q = ps8; + } + else + { + i1 = (ix << 16) | (i0 >> 16); + if (i1 >= 0x40019174) /* x >= 4.54541015625 */ + { + p = pr5; + q = ps5; + } + else if (i1 >= 0x4000b6db) /* x >= 2.85711669921875 */ + { + p = pr3; + q = ps3; + } + else if (ix >= 0x4000) /* x better be >= 2 */ + { + p = pr2; + q = ps2; + } + } + z = one / (x * x); + r = p[0] + z * (p[1] + + z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6]))))); + s = q[0] + z * (q[1] + z * (q[2] + z * (q[3] + z * (q[4] + z * (q[5] + z))))); + return one + z * r / s; +} + + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + */ + +/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x), + Q1(x) = z(.375 + z^2 R(z^2)), z=1/x + 8 <= x <= inf + Peak relative error 8.3e-22 */ + +#ifdef __STDC__ +static const long double qr8[7] = { +#else +static long double qr8[7] = { +#endif + -5.691925079044209246015366919809404457380E-10L, + -1.632587664706999307871963065396218379137E-7L, + -1.577424682764651970003637263552027114600E-5L, + -6.377627959241053914770158336842725291713E-4L, + -1.087408516779972735197277149494929568768E-2L, + -6.854943629378084419631926076882330494217E-2L, + -1.055448290469180032312893377152490183203E-1L, +}; +#ifdef __STDC__ +static const long double qs8[7] = { +#else +static long double qs8[7] = { +#endif + 5.550982172325019811119223916998393907513E-9L, + 1.607188366646736068460131091130644192244E-6L, + 1.580792530091386496626494138334505893599E-4L, + 6.617859900815747303032860443855006056595E-3L, + 1.212840547336984859952597488863037659161E-1L, + 9.017885953937234900458186716154005541075E-1L, + 2.201114489712243262000939120146436167178E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x), + Q1(x) = z(.375 + z^2 R(z^2)), z=1/x + 4.54541015625 <= x <= 8 + Peak relative error 4.1e-22 */ +#ifdef __STDC__ +static const long double qr5[7] = { +#else +static long double qr5[7] = { +#endif + -6.719134139179190546324213696633564965983E-8L, + -9.467871458774950479909851595678622044140E-6L, + -4.429341875348286176950914275723051452838E-4L, + -8.539898021757342531563866270278505014487E-3L, + -6.818691805848737010422337101409276287170E-2L, + -1.964432669771684034858848142418228214855E-1L, + -1.333896496989238600119596538299938520726E-1L, +}; +#ifdef __STDC__ +static const long double qs5[7] = { +#else +static long double qs5[7] = { +#endif + 6.552755584474634766937589285426911075101E-7L, + 9.410814032118155978663509073200494000589E-5L, + 4.561677087286518359461609153655021253238E-3L, + 9.397742096177905170800336715661091535805E-2L, + 8.518538116671013902180962914473967738771E-1L, + 3.177729183645800174212539541058292579009E0L, + 4.006745668510308096259753538973038902990E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x), + Q1(x) = z(.375 + z^2 R(z^2)), z=1/x + 2.85711669921875 <= x <= 4.54541015625 + Peak relative error 2.2e-21 */ +#ifdef __STDC__ +static const long double qr3[7] = { +#else +static long double qr3[7] = { +#endif + -3.618746299358445926506719188614570588404E-6L, + -2.951146018465419674063882650970344502798E-4L, + -7.728518171262562194043409753656506795258E-3L, + -8.058010968753999435006488158237984014883E-2L, + -3.356232856677966691703904770937143483472E-1L, + -4.858192581793118040782557808823460276452E-1L, + -1.592399251246473643510898335746432479373E-1L, +}; +#ifdef __STDC__ +static const long double qs3[7] = { +#else +static long double qs3[7] = { +#endif + 3.529139957987837084554591421329876744262E-5L, + 2.973602667215766676998703687065066180115E-3L, + 8.273534546240864308494062287908662592100E-2L, + 9.613359842126507198241321110649974032726E-1L, + 4.853923697093974370118387947065402707519E0L, + 1.002671608961669247462020977417828796933E1L, + 7.028927383922483728931327850683151410267E0L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + +/* Y1(x)cosX - J1(x)sinX = sqrt( 2/(pi x)) Q1(x), + Q1(x) = z(.375 + z^2 R(z^2)), z=1/x + 2 <= x <= 2.85711669921875 + Peak relative error 6.9e-22 */ +#ifdef __STDC__ +static const long double qr2[7] = { +#else +static long double qr2[7] = { +#endif + -1.372751603025230017220666013816502528318E-4L, + -6.879190253347766576229143006767218972834E-3L, + -1.061253572090925414598304855316280077828E-1L, + -6.262164224345471241219408329354943337214E-1L, + -1.423149636514768476376254324731437473915E0L, + -1.087955310491078933531734062917489870754E0L, + -1.826821119773182847861406108689273719137E-1L, +}; +#ifdef __STDC__ +static const long double qs2[7] = { +#else +static long double qs2[7] = { +#endif + 1.338768933634451601814048220627185324007E-3L, + 7.071099998918497559736318523932241901810E-2L, + 1.200511429784048632105295629933382142221E0L, + 8.327301713640367079030141077172031825276E0L, + 2.468479301872299311658145549931764426840E1L, + 2.961179686096262083509383820557051621644E1L, + 1.201402313144305153005639494661767354977E1L, + /* 1.000000000000000000000000000000000000000E0L, */ +}; + + +#ifdef __STDC__ +static long double +qone (long double x) +#else +static long double +qone (x) + long double x; +#endif +{ +#ifdef __STDC__ + const long double *p, *q; +#else + long double *p, *q; +#endif + static long double s, r, z; + int32_t ix; + u_int32_t se, i0, i1; + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + if (ix >= 0x4002) /* x >= 8 */ + { + p = qr8; + q = qs8; + } + else + { + i1 = (ix << 16) | (i0 >> 16); + if (i1 >= 0x40019174) /* x >= 4.54541015625 */ + { + p = qr5; + q = qs5; + } + else if (i1 >= 0x4000b6db) /* x >= 2.85711669921875 */ + { + p = qr3; + q = qs3; + } + else if (ix >= 0x4000) /* x better be >= 2 */ + { + p = qr2; + q = qs2; + } + } + z = one / (x * x); + r = + p[0] + z * (p[1] + + z * (p[2] + z * (p[3] + z * (p[4] + z * (p[5] + z * p[6]))))); + s = + q[0] + z * (q[1] + + z * (q[2] + + z * (q[3] + z * (q[4] + z * (q[5] + z * (q[6] + z)))))); + return (.375 + z * r / s) / x; +} diff --git a/src/system/libroot/posix/glibc/arch/generic/e_jnl.c b/src/system/libroot/posix/glibc/arch/generic/e_jnl.c new file mode 100644 index 0000000000..3d715d36aa --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_jnl.c @@ -0,0 +1,386 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* Modifications for long double are + Copyright (C) 2001 Stephen L. Moshier + and are incorporated herein by permission of the author. The author + reserves the right to distribute this material elsewhere under different + copying permissions. These modifications are distributed here under + the following terms: + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + * __ieee754_jn(n, x), __ieee754_yn(n, x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with overflow signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double +#else +static long double +#endif + invsqrtpi = 5.64189583547756286948079e-1L, two = 2.0e0L, one = 1.0e0L; + +#ifdef __STDC__ +static const long double zero = 0.0L; +#else +static long double zero = 0.0L; +#endif + +#ifdef __STDC__ +long double +__ieee754_jnl (int n, long double x) +#else +long double +__ieee754_jnl (n, x) + int n; + long double x; +#endif +{ + u_int32_t se, i0, i1; + int32_t i, ix, sgn; + long double a, b, temp, di; + long double z, w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + + /* if J(n,NaN) is NaN */ + if ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0)) + return x + x; + if (n < 0) + { + n = -n; + x = -x; + se ^= 0x8000; + } + if (n == 0) + return (__ieee754_j0l (x)); + if (n == 1) + return (__ieee754_j1l (x)); + sgn = (n & 1) & (se >> 15); /* even n -- 0, odd n -- sign(x) */ + x = fabsl (x); + if ((ix | i0 | i1) == 0 || ix >= 0x7fff) /* if x is 0 or inf */ + b = zero; + else if ((long double) n <= x) + { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if (ix >= 0x412D) + { /* x > 2**302 */ + + /* ??? This might be a futile gesture. + If x exceeds X_TLOSS anyway, the wrapper function + will set the result to zero. */ + + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + long double s; + long double c; + __sincosl (x, &s, &c); + switch (n & 3) + { + case 0: + temp = c + s; + break; + case 1: + temp = -c + s; + break; + case 2: + temp = -c - s; + break; + case 3: + temp = c - s; + break; + } + b = invsqrtpi * temp / __ieee754_sqrtl (x); + } + else + { + a = __ieee754_j0l (x); + b = __ieee754_j1l (x); + for (i = 1; i < n; i++) + { + temp = b; + b = b * ((long double) (i + i) / x) - a; /* avoid underflow */ + a = temp; + } + } + } + else + { + if (ix < 0x3fde) + { /* x < 2**-33 */ + /* x is tiny, return the first Taylor expansion of J(n,x) + * J(n,x) = 1/n!*(x/2)^n - ... + */ + if (n >= 400) /* underflow, result < 10^-4952 */ + b = zero; + else + { + temp = x * 0.5; + b = temp; + for (a = one, i = 2; i <= n; i++) + { + a *= (long double) i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + b = b / a; + } + } + else + { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + long double t, v; + long double q0, q1, h, tmp; + int32_t k, m; + w = (n + n) / (long double) x; + h = 2.0L / (long double) x; + q0 = w; + z = w + h; + q1 = w * z - 1.0L; + k = 1; + while (q1 < 1.0e11L) + { + k += 1; + z += h; + tmp = z * q1 - q0; + q0 = q1; + q1 = tmp; + } + m = n + n; + for (t = zero, i = 2 * (n + k); i >= m; i -= 2) + t = one / (i / x - t); + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = n; + v = two / x; + tmp = tmp * __ieee754_logl (fabsl (v * tmp)); + + if (tmp < 1.1356523406294143949491931077970765006170e+04L) + { + for (i = n - 1, di = (long double) (i + i); i > 0; i--) + { + temp = b; + b *= di; + b = b / x - a; + a = temp; + di -= two; + } + } + else + { + for (i = n - 1, di = (long double) (i + i); i > 0; i--) + { + temp = b; + b *= di; + b = b / x - a; + a = temp; + di -= two; + /* scale b to avoid spurious overflow */ + if (b > 1e100L) + { + a /= b; + t /= b; + b = one; + } + } + } + b = (t * __ieee754_j0l (x) / b); + } + } + if (sgn == 1) + return -b; + else + return b; +} + +#ifdef __STDC__ +long double +__ieee754_ynl (int n, long double x) +#else +long double +__ieee754_ynl (n, x) + int n; + long double x; +#endif +{ + u_int32_t se, i0, i1; + int32_t i, ix; + int32_t sign; + long double a, b, temp; + + + GET_LDOUBLE_WORDS (se, i0, i1, x); + ix = se & 0x7fff; + /* if Y(n,NaN) is NaN */ + if ((ix == 0x7fff) && ((i0 & 0x7fffffff) != 0)) + return x + x; + if ((ix | i0 | i1) == 0) + return -HUGE_VALL + x; /* -inf and overflow exception. */ + if (se & 0x8000) + return zero / (zero * x); + sign = 1; + if (n < 0) + { + n = -n; + sign = 1 - ((n & 1) << 1); + } + if (n == 0) + return (__ieee754_y0l (x)); + if (n == 1) + return (sign * __ieee754_y1l (x)); + if (ix == 0x7fff) + return zero; + if (ix >= 0x412D) + { /* x > 2**302 */ + + /* ??? See comment above on the possible futility of this. */ + + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + long double s; + long double c; + __sincosl (x, &s, &c); + switch (n & 3) + { + case 0: + temp = s - c; + break; + case 1: + temp = -s - c; + break; + case 2: + temp = -s + c; + break; + case 3: + temp = s + c; + break; + } + b = invsqrtpi * temp / __ieee754_sqrtl (x); + } + else + { + a = __ieee754_y0l (x); + b = __ieee754_y1l (x); + /* quit if b is -inf */ + GET_LDOUBLE_WORDS (se, i0, i1, b); + for (i = 1; i < n && se != 0xffff; i++) + { + temp = b; + b = ((long double) (i + i) / x) * b - a; + GET_LDOUBLE_WORDS (se, i0, i1, b); + a = temp; + } + } + if (sign > 0) + return b; + else + return -b; +} diff --git a/src/system/libroot/posix/glibc/arch/generic/e_rem_pio2.c b/src/system/libroot/posix/glibc/arch/generic/e_rem_pio2.c new file mode 100644 index 0000000000..a8a8cdb2b2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_rem_pio2.c @@ -0,0 +1,183 @@ +/* @(#)e_rem_pio2.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $"; +#endif + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2() + */ + +#include "math.h" +#include "math_private.h" + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +#ifdef __STDC__ +static const int32_t two_over_pi[] = { +#else +static int32_t two_over_pi[] = { +#endif +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +#ifdef __STDC__ +static const int32_t npio2_hw[] = { +#else +static int32_t npio2_hw[] = { +#endif +0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, +0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, +0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, +0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, +0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, +0x404858EB, 0x404921FB, +}; + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +#ifdef __STDC__ + int32_t __ieee754_rem_pio2(double x, double *y) +#else + int32_t __ieee754_rem_pio2(x,y) + double x,y[]; +#endif +{ + double z,w,t,r,fn; + double tx[3]; + int32_t e0,i,j,nx,n,ix,hx; + u_int32_t low; + + GET_HIGH_WORD(hx,x); /* high word of x */ + ix = hx&0x7fffffff; + if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ + {y[0] = x; y[1] = 0; return 0;} + if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if(hx>0) { + z = x - pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z-y[0])-pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z-y[0])-pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z-y[0])+pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z-y[0])+pio2_2t; + } + return -1; + } + } + if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int32_t) (t*invpio2+half); + fn = (double)n; + r = t-fn*pio2_1; + w = fn*pio2_1t; /* 1st round good to 85 bit */ + if(n<32&&ix!=npio2_hw[n-1]) { + y[0] = r-w; /* quick check no cancellation */ + } else { + u_int32_t high; + j = ix>>20; + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn*pio2_2; + r = t-w; + w = fn*pio2_2t-((t-r)-w); + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn*pio2_3; + r = t-w; + w = fn*pio2_3t-((t-r)-w); + y[0] = r-w; + } + } + } + y[1] = (r-y[0])-w; + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + else return n; + } + /* + * all other (large) arguments + */ + if(ix>=0x7ff00000) { /* x is inf or NaN */ + y[0]=y[1]=x-x; return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + GET_LOW_WORD(low,x); + SET_LOW_WORD(z,low); + e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20))); + for(i=0;i<2;i++) { + tx[i] = (double)((int32_t)(z)); + z = (z-tx[i])*two24; + } + tx[2] = z; + nx = 3; + while(tx[nx-1]==zero) nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + return n; +} diff --git a/src/system/libroot/posix/glibc/arch/generic/s_asinhl.c b/src/system/libroot/posix/glibc/arch/generic/s_asinhl.c new file mode 100644 index 0000000000..6eb434c44b --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_asinhl.c @@ -0,0 +1,70 @@ +/* s_asinhl.c -- long double version of s_asinh.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* asinhl(x) + * Method : + * Based on + * asinhl(x) = signl(x) * logl [ |x| + sqrtl(x*x+1) ] + * we have + * asinhl(x) := x if 1+x*x=1, + * := signl(x)*(logl(x)+ln2)) for large |x|, else + * := signl(x)*logl(2|x|+1/(|x|+sqrtl(x*x+1))) if|x|>2, else + * := signl(x)*log1pl(|x| + x^2/(1 + sqrtl(1+x^2))) + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double +#else +static long double +#endif +one = 1.000000000000000000000e+00L, /* 0x3FFF, 0x00000000, 0x00000000 */ +ln2 = 6.931471805599453094287e-01L, /* 0x3FFE, 0xB17217F7, 0xD1CF79AC */ +huge= 1.000000000000000000e+4900L; + +#ifdef __STDC__ + long double __asinhl(long double x) +#else + long double __asinhl(x) + long double x; +#endif +{ + long double t,w; + int32_t hx,ix; + GET_LDOUBLE_EXP(hx,x); + ix = hx&0x7fff; + if(ix==0x7fff) return x+x; /* x is inf or NaN */ + if(ix< 0x3fde) { /* |x|<2**-34 */ + if(huge+x>one) return x; /* return x inexact except 0 */ + } + if(ix>0x4020) { /* |x| > 2**34 */ + w = __ieee754_logl(fabsl(x))+ln2; + } else if (ix>0x4000) { /* 2**34 > |x| > 2.0 */ + t = fabsl(x); + w = __ieee754_logl(2.0*t+one/(__ieee754_sqrtl(x*x+one)+t)); + } else { /* 2.0 > |x| > 2**-28 */ + t = x*x; + w =__log1pl(fabsl(x)+t/(one+__ieee754_sqrtl(one+t))); + } + if(hx&0x8000) return -w; else return w; +} +weak_alias (__asinhl, asinhl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_cbrtl.c b/src/system/libroot/posix/glibc/arch/generic/s_cbrtl.c new file mode 100644 index 0000000000..0f8227a04b --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_cbrtl.c @@ -0,0 +1,71 @@ +/* Compute cubic root of double value. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Dirk Alboth and + Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "math.h" +#include "math_private.h" + + +#define CBRT2 1.2599210498948731648 /* 2^(1/3) */ +#define SQR_CBRT2 1.5874010519681994748 /* 2^(2/3) */ + +/* We don't use long double values here since U need not be computed + with full precision. */ +static const double factor[5] = +{ + 1.0 / SQR_CBRT2, + 1.0 / CBRT2, + 1.0, + CBRT2, + SQR_CBRT2 +}; + +static const long double third = 0.3333333333333333333333333L; + +long double +__cbrtl (long double x) +{ + long double xm, u; + int xe; + + /* Reduce X. XM now is an range 1.0 to 0.5. */ + xm = __frexpl (fabs (x), &xe); + + /* If X is not finite or is null return it (with raising exceptions + if necessary. + Note: *Our* version of `frexp' sets XE to zero if the argument is + Inf or NaN. This is not portable but faster. */ + if (xe == 0 && fpclassify (x) <= FP_ZERO) + return x + x; + + u = (((-1.34661104733595206551E-1 * xm + + 5.46646013663955245034E-1) * xm + - 9.54382247715094465250E-1) * xm + + 1.13999833547172932737E0) * xm + + 4.02389795645447521269E-1; + + u *= factor[2 + xe % 3]; + u = __ldexpl (x > 0.0 ? u : -u, xe / 3); + + u -= (u - (x / (u * u))) * third; + u -= (u - (x / (u * u))) * third; + return u; +} +weak_alias (__cbrtl, cbrtl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_fdim.c b/src/system/libroot/posix/glibc/arch/generic/s_fdim.c new file mode 100644 index 0000000000..5804e631c3 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_fdim.c @@ -0,0 +1,40 @@ +/* Return positive difference between arguments. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +double +__fdim (double x, double y) +{ + int clsx = fpclassify (x); + int clsy = fpclassify (y); + + if (clsx == FP_NAN || clsy == FP_NAN + || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE)) + /* Raise invalid flag. */ + return x - y; + + return x <= y ? 0 : x - y; +} +weak_alias (__fdim, fdim) +#ifdef NO_LONG_DOUBLE +strong_alias (__fdim, __fdiml) +weak_alias (__fdim, fdiml) +#endif diff --git a/src/system/libroot/posix/glibc/arch/generic/s_fdimf.c b/src/system/libroot/posix/glibc/arch/generic/s_fdimf.c new file mode 100644 index 0000000000..2f3ce303ae --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_fdimf.c @@ -0,0 +1,36 @@ +/* Return positive difference between arguments. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +float +__fdimf (float x, float y) +{ + int clsx = fpclassify (x); + int clsy = fpclassify (y); + + if (clsx == FP_NAN || clsy == FP_NAN + || (y < 0 && clsx == FP_INFINITE && clsy == FP_INFINITE)) + /* Raise invalid flag. */ + return x - y; + + return x <= y ? 0 : x - y; +} +weak_alias (__fdimf, fdimf) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_frexpl.c b/src/system/libroot/posix/glibc/arch/generic/s_frexpl.c new file mode 100644 index 0000000000..0caa90b035 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_frexpl.c @@ -0,0 +1,70 @@ +/* s_frexpl.c -- long double version of s_frexp.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* + * for non-zero x + * x = frexpl(arg,&exp); + * return a long double fp quantity x such that 0.5 <= |x| <1.0 + * and the corresponding binary exponent "exp". That is + * arg = x*2^exp. + * If arg is inf, 0.0, or NaN, then frexpl(arg,&exp) returns arg + * with *exp=0. + */ + +#include +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double +#else +static long double +#endif +#if LDBL_MANT_DIG == 64 +two65 = 3.68934881474191032320e+19L; /* 0x4040, 0x80000000, 0x00000000 */ +#else +# error "Cannot handle this MANT_DIG" +#endif + + +#ifdef __STDC__ + long double __frexpl(long double x, int *eptr) +#else + long double __frexpl(x, eptr) + long double x; int *eptr; +#endif +{ + u_int32_t se, hx, ix, lx; + GET_LDOUBLE_WORDS(se,hx,lx,x); + ix = 0x7fff&se; + *eptr = 0; + if(ix==0x7fff||((ix|hx|lx)==0)) return x; /* 0,inf,nan */ + if (ix==0x0000) { /* subnormal */ + x *= two65; + GET_LDOUBLE_EXP(se,x); + ix = se&0x7fff; + *eptr = -65; + } + *eptr += ix-16382; + se = (se & 0x8000) | 0x3ffe; + SET_LDOUBLE_EXP(x,se); + return x; +} +weak_alias (__frexpl, frexpl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_ldexpl.c b/src/system/libroot/posix/glibc/arch/generic/s_ldexpl.c new file mode 100644 index 0000000000..df8b29f94d --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_ldexpl.c @@ -0,0 +1,37 @@ +/* s_ldexpl.c -- long double version of s_ldexp.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +#include +#include "math_private.h" +#include + +#ifdef __STDC__ + long double __ldexpl(long double value, int exp) +#else + long double __ldexpl(value, exp) + long double value; int exp; +#endif +{ + if(!__finitel(value)||value==0.0) return value; + value = __scalbnl(value,exp); + if(!__finitel(value)||value==0.0) __set_errno (ERANGE); + return value; +} +weak_alias (__ldexpl, ldexpl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_nearbyint.c b/src/system/libroot/posix/glibc/arch/generic/s_nearbyint.c new file mode 100644 index 0000000000..71e14cfb6d --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_nearbyint.c @@ -0,0 +1,105 @@ +/* Adapted for use as nearbyint by Ulrich Drepper . */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $"; +#endif + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double __nearbyint(double x) +#else + double __nearbyint(x) + double x; +#endif +{ + fenv_t env; + int32_t i0,j0,sx; + u_int32_t i,i1; + double w,t; + EXTRACT_WORDS(i0,i1,x); + sx = (i0>>31)&1; + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { + if(((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + SET_HIGH_WORD(x,i0); + feholdexcept (&env); + w = TWO52[sx]+x; + t = w-TWO52[sx]; + fesetenv (&env); + GET_HIGH_WORD(i0,t); + SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if(((i0&i)|i1)!=0) { + if (j0==19) + i1 = 0x40000000; + else if (j0<18) + i0 = (i0&(~i))|((0x20000)>>j0); + else + { + i0 &= ~i; + i1 = 0x80000000; + } + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + i>>=1; + if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + INSERT_WORDS(x,i0,i1); + feholdexcept (&env); + w = TWO52[sx]+x; + t = w-TWO52[sx]; + fesetenv (&env); + return t; +} +weak_alias (__nearbyint, nearbyint) +#ifdef NO_LONG_DOUBLE +strong_alias (__nearbyint, __nearbyintl) +weak_alias (__nearbyint, nearbyintl) +#endif diff --git a/src/system/libroot/posix/glibc/arch/generic/s_nearbyintf.c b/src/system/libroot/posix/glibc/arch/generic/s_nearbyintf.c new file mode 100644 index 0000000000..7d6f262f51 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_nearbyintf.c @@ -0,0 +1,77 @@ +/* s_rintf.c -- float version of s_rint.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ +/* Adapted for use as nearbyint by Ulrich Drepper . */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + + +#include +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +#ifdef __STDC__ + float __nearbyintf(float x) +#else + float __nearbyintf(x) + float x; +#endif +{ + fenv_t env; + int32_t i0,j0,sx; + u_int32_t i,i1; + float w,t; + GET_FLOAT_WORD(i0,x); + sx = (i0>>31)&1; + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { + if((i0&0x7fffffff)==0) return x; + i1 = (i0&0x07fffff); + i0 &= 0xfff00000; + i0 |= ((i1|-i1)>>9)&0x400000; + SET_FLOAT_WORD(x,i0); + feholdexcept (&env); + w = TWO23[sx]+x; + t = w-TWO23[sx]; + fesetenv (&env); + GET_FLOAT_WORD(i0,t); + SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + i>>=1; + if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>j0); + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + feholdexcept (&env); + w = TWO23[sx]+x; + t = w-TWO23[sx]; + fesetenv (&env); + return t; +} +weak_alias (__nearbyintf, nearbyintf) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_rint.c b/src/system/libroot/posix/glibc/arch/generic/s_rint.c new file mode 100644 index 0000000000..4e6381efbe --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_rint.c @@ -0,0 +1,98 @@ +/* @(#)s_rint.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $"; +#endif + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +#ifdef __STDC__ + double __rint(double x) +#else + double __rint(x) + double x; +#endif +{ + int32_t i0,j0,sx; + u_int32_t i,i1; + double w,t; + EXTRACT_WORDS(i0,i1,x); + sx = (i0>>31)&1; + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { + if(((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + SET_HIGH_WORD(x,i0); + w = TWO52[sx]+x; + t = w-TWO52[sx]; + GET_HIGH_WORD(i0,t); + SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if(((i0&i)|i1)!=0) { + if (j0==19) + i1 = 0x40000000; + else if (j0<18) + i0 = (i0&(~i))|((0x20000)>>j0); + else + { + i0 &= ~i; + i1 = 0x80000000; + } + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + i>>=1; + if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + INSERT_WORDS(x,i0,i1); + w = TWO52[sx]+x; + return w-TWO52[sx]; +} +weak_alias (__rint, rint) +#ifdef NO_LONG_DOUBLE +strong_alias (__rint, __rintl) +weak_alias (__rint, rintl) +#endif diff --git a/src/system/libroot/posix/glibc/arch/generic/s_rintf.c b/src/system/libroot/posix/glibc/arch/generic/s_rintf.c new file mode 100644 index 0000000000..4e5b409b29 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_rintf.c @@ -0,0 +1,72 @@ +/* s_rintf.c -- float version of s_rint.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_rintf.c,v 1.4 1995/05/10 20:48:06 jtc Exp $"; +#endif + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +#ifdef __STDC__ + float __rintf(float x) +#else + float __rintf(x) + float x; +#endif +{ + int32_t i0,j0,sx; + u_int32_t i,i1; + float w,t; + GET_FLOAT_WORD(i0,x); + sx = (i0>>31)&1; + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { + if((i0&0x7fffffff)==0) return x; + i1 = (i0&0x07fffff); + i0 &= 0xfff00000; + i0 |= ((i1|-i1)>>9)&0x400000; + SET_FLOAT_WORD(x,i0); + w = TWO23[sx]+x; + t = w-TWO23[sx]; + GET_FLOAT_WORD(i0,t); + SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + i>>=1; + if((i0&i)!=0) i0 = (i0&(~i))|((0x100000)>>j0); + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + w = TWO23[sx]+x; + return w-TWO23[sx]; +} +weak_alias (__rintf, rintf) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_scalbln.c b/src/system/libroot/posix/glibc/arch/generic/s_scalbln.c new file mode 100644 index 0000000000..aa6134f093 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_scalbln.c @@ -0,0 +1,70 @@ +/* @(#)s_scalbn.c 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_scalbn.c,v 1.8 1995/05/10 20:48:08 jtc Exp $"; +#endif + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const double +#else +static double +#endif +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +#ifdef __STDC__ + double __scalbln (double x, long int n) +#else + double __scalbln (x,n) + double x; long int n; +#endif +{ + int32_t k,hx,lx; + EXTRACT_WORDS(hx,lx,x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx,x); + k = ((hx&0x7ff00000)>>20) - 54; + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (n> 50000 || k > 0x7fe) + return huge*__copysign(huge,x); /* overflow */ + if (n< -50000) return tiny*__copysign(tiny,x); /*underflow*/ + if (k > 0) /* normal result */ + {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;} + if (k <= -54) + return tiny*__copysign(tiny,x); /*underflow*/ + k += 54; /* subnormal result */ + SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); + return x*twom54; +} +weak_alias (__scalbln, scalbln) +#ifdef NO_LONG_DOUBLE +strong_alias (__scalbln, __scalblnl) +weak_alias (__scalbln, scalblnl) +#endif diff --git a/src/system/libroot/posix/glibc/arch/generic/s_scalblnf.c b/src/system/libroot/posix/glibc/arch/generic/s_scalblnf.c new file mode 100644 index 0000000000..4ed48733cf --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_scalblnf.c @@ -0,0 +1,63 @@ +/* s_scalbnf.c -- float version of s_scalbn.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: s_scalbnf.c,v 1.4 1995/05/10 20:48:10 jtc Exp $"; +#endif + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +two25 = 3.355443200e+07, /* 0x4c000000 */ +twom25 = 2.9802322388e-08, /* 0x33000000 */ +huge = 1.0e+30, +tiny = 1.0e-30; + +#ifdef __STDC__ + float __scalblnf (float x, long int n) +#else + float __scalblnf (x,n) + float x; long int n; +#endif +{ + int32_t k,ix; + GET_FLOAT_WORD(ix,x); + k = (ix&0x7f800000)>>23; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((ix&0x7fffffff)==0) return x; /* +-0 */ + x *= two25; + GET_FLOAT_WORD(ix,x); + k = ((ix&0x7f800000)>>23) - 25; + } + if (k==0xff) return x+x; /* NaN or Inf */ + k = k+n; + if (n> 50000 || k > 0xfe) + return huge*copysignf(huge,x); /* overflow */ + if (n< -50000) + return tiny*copysignf(tiny,x); /*underflow*/ + if (k > 0) /* normal result */ + {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;} + if (k <= -25) + return tiny*copysignf(tiny,x); /*underflow*/ + k += 25; /* subnormal result */ + SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); + return x*twom25; +} +weak_alias (__scalblnf, scalblnf) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_scalblnl.c b/src/system/libroot/posix/glibc/arch/generic/s_scalblnl.c new file mode 100644 index 0000000000..8e556fabe1 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_scalblnl.c @@ -0,0 +1,71 @@ +/* s_scalbnl.c -- long double version of s_scalbn.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* + * scalbnl (long double x, int n) + * scalbnl(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double +#else +static long double +#endif +two63 = 4.50359962737049600000e+15, +twom63 = 1.08420217248550443400e-19, +huge = 1.0e+4900L, +tiny = 1.0e-4900L; + +#ifdef __STDC__ + long double __scalblnl (long double x, long int n) +#else + long double __scalblnl (x,n) + long double x; long int n; +#endif +{ + int32_t k,es,hx,lx; + GET_LDOUBLE_WORDS(es,hx,lx,x); + k = es&0x7fff; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two63; + GET_LDOUBLE_EXP(es,x); + k = (hx&0x7fff) - 63; + } + if (k==0x7fff) return x+x; /* NaN or Inf */ + k = k+n; + if (n> 50000 || k > 0x7ffe) + return huge*__copysignl(huge,x); /* overflow */ + if (n< -50000) + return tiny*__copysignl(tiny,x); + if (k > 0) /* normal result */ + {SET_LDOUBLE_EXP(x,(es&0x8000)|k); return x;} + if (k <= -63) + return tiny*__copysignl(tiny,x); /*underflow*/ + k += 63; /* subnormal result */ + SET_LDOUBLE_EXP(x,(es&0x8000)|k); + return x*twom63; +} +weak_alias (__scalblnl, scalblnl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_tanhl.c b/src/system/libroot/posix/glibc/arch/generic/s_tanhl.c new file mode 100644 index 0000000000..45cea903e3 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_tanhl.c @@ -0,0 +1,95 @@ +/* s_tanhl.c -- long double version of s_tanh.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* tanhl(x) + * Return the Hyperbolic Tangent of x + * + * Method : + * x -x + * e - e + * 0. tanhl(x) is defined to be ----------- + * x -x + * e + e + * 1. reduce x to non-negative by tanhl(-x) = -tanhl(x). + * 2. 0 <= x <= 2**-55 : tanhl(x) := x*(one+x) + * -t + * 2**-55 < x <= 1 : tanhl(x) := -----; t = expm1l(-2x) + * t + 2 + * 2 + * 1 <= x <= 23.0 : tanhl(x) := 1- ----- ; t=expm1l(2x) + * t + 2 + * 23.0 < x <= INF : tanhl(x) := 1. + * + * Special cases: + * tanhl(NaN) is NaN; + * only tanhl(0)=0 is exact for finite argument. + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ +static const long double one=1.0, two=2.0, tiny = 1.0e-4900L; +#else +static long double one=1.0, two=2.0, tiny = 1.0e-4900L; +#endif + +#ifdef __STDC__ + long double __tanhl(long double x) +#else + long double __tanhl(x) + long double x; +#endif +{ + long double t,z; + int32_t se; + u_int32_t j0,j1,ix; + + /* High word of |x|. */ + GET_LDOUBLE_WORDS(se,j0,j1,x); + ix = se&0x7fff; + + /* x is INF or NaN */ + if(ix==0x7fff) { + /* for NaN it's not important which branch: tanhl(NaN) = NaN */ + if (se&0x8000) return one/x-one; /* tanhl(-inf)= -1; */ + else return one/x+one; /* tanhl(+inf)=+1 */ + } + + /* |x| < 23 */ + if (ix < 0x4003 || (ix == 0x4003 && j0 < 0xb8000000u)) {/* |x|<23 */ + if ((ix|j0|j1) == 0) + return x; /* x == +- 0 */ + if (ix<0x3fc8) /* |x|<2**-55 */ + return x*(one+tiny); /* tanh(small) = small */ + if (ix>=0x3fff) { /* |x|>=1 */ + t = __expm1l(two*fabsl(x)); + z = one - two/(t+two); + } else { + t = __expm1l(-two*fabsl(x)); + z= -t/(t+two); + } + /* |x| > 23, return +-1 */ + } else { + z = one - tiny; /* raised inexact flag */ + } + return (se&0x8000)? -z: z; +} +weak_alias (__tanhl, tanhl) diff --git a/src/system/libroot/posix/glibc/arch/generic/t_exp2.h b/src/system/libroot/posix/glibc/arch/generic/t_exp2.h new file mode 100644 index 0000000000..1fd73338cf --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/t_exp2.h @@ -0,0 +1,585 @@ +/* These values are accurate to 52+12 bits when represented as + a double. */ +static const double exp2_accuratetable[512] = { +0.707106781187802013759 /* 0x0.b504f333fb3f80007 */, +0.708064712808760599040 /* 0x0.b543baa0f71b38000 */, +0.709023942160304065938 /* 0x0.b58297d3a8d518002 */, +0.709984470998547667624 /* 0x0.b5c18ad39b4ba0001 */, +0.710946301084324217006 /* 0x0.b60093a85e8d30001 */, +0.711909434180505784637 /* 0x0.b63fb25984e628005 */, +0.712873872052760648733 /* 0x0.b67ee6eea3b5f8003 */, +0.713839616467838999908 /* 0x0.b6be316f518c98001 */, +0.714806669195984345523 /* 0x0.b6fd91e328d148007 */, +0.715775032009894562898 /* 0x0.b73d0851c69e20002 */, +0.716744706683768884058 /* 0x0.b77c94c2c9b3d0003 */, +0.717715694995770148178 /* 0x0.b7bc373dd52eb0003 */, +0.718687998724665488852 /* 0x0.b7fbefca8cd530004 */, +0.719661619652575468291 /* 0x0.b83bbe70981da8001 */, +0.720636559564428180758 /* 0x0.b87ba337a194b0006 */, +0.721612820246623098989 /* 0x0.b8bb9e27556508004 */, +0.722590403488338473025 /* 0x0.b8fbaf4762c798006 */, +0.723569311081411870036 /* 0x0.b93bd69f7be1d0000 */, +0.724549544820974333906 /* 0x0.b97c1437567828007 */, +0.725531106502312561633 /* 0x0.b9bc6816a87ae8002 */, +0.726513997924421062181 /* 0x0.b9fcd2452bee00000 */, +0.727498220889519875430 /* 0x0.ba3d52ca9e6148002 */, +0.728483777200401694265 /* 0x0.ba7de9aebe05c8003 */, +0.729470668664712662563 /* 0x0.babe96f94e62a8002 */, +0.730458897090379144517 /* 0x0.baff5ab2134df0004 */, +0.731448464287988597833 /* 0x0.bb4034e0d38ab0000 */, +0.732439372072965166897 /* 0x0.bb81258d5b2d60001 */, +0.733431622260458326859 /* 0x0.bbc22cbf75fd28001 */, +0.734425216668725511232 /* 0x0.bc034a7ef32c00001 */, +0.735420157118880535324 /* 0x0.bc447ed3a50fe0005 */, +0.736416445434497690674 /* 0x0.bc85c9c560b350001 */, +0.737414083433310718618 /* 0x0.bcc72b5bf4b4e0000 */, +0.738413072966152328496 /* 0x0.bd08a39f5417a8007 */, +0.739413415848264365956 /* 0x0.bd4a32974abcd0002 */, +0.740415113911250699637 /* 0x0.bd8bd84bb68300002 */, +0.741418168994518067562 /* 0x0.bdcd94c47ddd30003 */, +0.742422582936659858376 /* 0x0.be0f6809865968006 */, +0.743428357577745613238 /* 0x0.be515222b72530003 */, +0.744435494762383687126 /* 0x0.be935317fc6ba0002 */, +0.745443996335090397492 /* 0x0.bed56af1423de8001 */, +0.746453864145572798553 /* 0x0.bf1799b67a6248007 */, +0.747465100043933849969 /* 0x0.bf59df6f970e70002 */, +0.748477705883256683178 /* 0x0.bf9c3c248dbee8001 */, +0.749491683518965001732 /* 0x0.bfdeafdd568308000 */, +0.750507034813367890373 /* 0x0.c0213aa1f0fc38004 */, +0.751523761622240105153 /* 0x0.c063dc7a559ca0003 */, +0.752541865811731880422 /* 0x0.c0a6956e883ed8000 */, +0.753561349247157341600 /* 0x0.c0e965868bd220006 */, +0.754582213796583967110 /* 0x0.c12c4cca664cb8002 */, +0.755604461332336940791 /* 0x0.c16f4b42225350006 */, +0.756628093726406381068 /* 0x0.c1b260f5ca2c48002 */, +0.757653112855631305506 /* 0x0.c1f58ded6d72d8001 */, +0.758679520599333412360 /* 0x0.c238d2311e7d08001 */, +0.759707318837184453227 /* 0x0.c27c2dc8f00368005 */, +0.760736509456435783249 /* 0x0.c2bfa0bcfd1400000 */, +0.761767094336480043995 /* 0x0.c3032b155818d0000 */, +0.762799075372231349951 /* 0x0.c346ccda248cc0001 */, +0.763832454453522768941 /* 0x0.c38a8613805488005 */, +0.764867233473625618441 /* 0x0.c3ce56c98d1ca8005 */, +0.765903414329434539816 /* 0x0.c4123f04708d80002 */, +0.766940998920452976510 /* 0x0.c4563ecc532dc0001 */, +0.767979989148100838946 /* 0x0.c49a56295f9f88006 */, +0.769020386915772125040 /* 0x0.c4de8523c2b0a0001 */, +0.770062194131770905170 /* 0x0.c522cbc3ae94e0003 */, +0.771105412703856241146 /* 0x0.c5672a1154e6b8004 */, +0.772150044545352520777 /* 0x0.c5aba014ed5f18003 */, +0.773196091570364285606 /* 0x0.c5f02dd6b09288003 */, +0.774243555696622731700 /* 0x0.c634d35edb1260003 */, +0.775292438842697939641 /* 0x0.c67990b5aa5c18004 */, +0.776342742931542928455 /* 0x0.c6be65e360bed8000 */, +0.777394469888802008854 /* 0x0.c70352f0437f50004 */, +0.778447621641124243320 /* 0x0.c74857e498fd00006 */, +0.779502200118583399303 /* 0x0.c78d74c8ab5b60000 */, +0.780558207255445668515 /* 0x0.c7d2a9a4c959f8000 */, +0.781615644985491186966 /* 0x0.c817f681412f80002 */, +0.782674515247667956808 /* 0x0.c85d5b6666c150006 */, +0.783734819983036512536 /* 0x0.c8a2d85c904760003 */, +0.784796561133562109454 /* 0x0.c8e86d6c14f850002 */, +0.785859740645942328471 /* 0x0.c92e1a9d513ec8002 */, +0.786924360469767103536 /* 0x0.c973dff8a4b390007 */, +0.787990422552312885808 /* 0x0.c9b9bd866c6440007 */, +0.789057928854407064640 /* 0x0.c9ffb34f1444b0001 */, +0.790126881326406182996 /* 0x0.ca45c15afcc570001 */, +0.791197281930050233534 /* 0x0.ca8be7b292db38000 */, +0.792269132620954885659 /* 0x0.cad2265e3cbee8000 */, +0.793342435380726906957 /* 0x0.cb187d667d3d38006 */, +0.794417192158282659010 /* 0x0.cb5eecd3b33158006 */, +0.795493404931386649540 /* 0x0.cba574ae5d2e80001 */, +0.796571075671306805268 /* 0x0.cbec14fef2a348004 */, +0.797650206352955137846 /* 0x0.cc32cdcdef0000000 */, +0.798730798954342069432 /* 0x0.cc799f23d11d18000 */, +0.799812855456121796232 /* 0x0.ccc089091abb28004 */, +0.800896377841454287795 /* 0x0.cd078b86505c18003 */, +0.801981368096190028208 /* 0x0.cd4ea6a3f97720007 */, +0.803067828208752554378 /* 0x0.cd95da6aa057b8007 */, +0.804155760170129796375 /* 0x0.cddd26e2d21b28001 */, +0.805245165974338261710 /* 0x0.ce248c151f3330001 */, +0.806336047619038653883 /* 0x0.ce6c0a0a1c1350001 */, +0.807428407102107836855 /* 0x0.ceb3a0ca5d6be0006 */, +0.808522246427078927792 /* 0x0.cefb505e7e2550007 */, +0.809617567597010201484 /* 0x0.cf4318cf18a268002 */, +0.810714372621179513182 /* 0x0.cf8afa24ce1c98004 */, +0.811812663508675536069 /* 0x0.cfd2f4683f9810005 */, +0.812912442272482604912 /* 0x0.d01b07a2126188003 */, +0.814013710929394895825 /* 0x0.d06333daeff618001 */, +0.815116471495287542325 /* 0x0.d0ab791b80d028006 */, +0.816220725993571205593 /* 0x0.d0f3d76c75b330000 */, +0.817326476447408967199 /* 0x0.d13c4ed67f1cf8000 */, +0.818433724883006474832 /* 0x0.d184df6250e3b0001 */, +0.819542473330909460055 /* 0x0.d1cd8918a3a328004 */, +0.820652723822034690935 /* 0x0.d2164c02305fa0002 */, +0.821764478391968422618 /* 0x0.d25f2827b53fb0005 */, +0.822877739077315761840 /* 0x0.d2a81d91f188b8000 */, +0.823992507918612782109 /* 0x0.d2f12c49a8d290005 */, +0.825108786960634610365 /* 0x0.d33a5457a35e40003 */, +0.826226578247117093869 /* 0x0.d38395c4a84848007 */, +0.827345883828319528258 /* 0x0.d3ccf09985d958004 */, +0.828466705754248966560 /* 0x0.d41664df0a1320005 */, +0.829589046080638992111 /* 0x0.d45ff29e094330000 */, +0.830712906863802391671 /* 0x0.d4a999df585a20005 */, +0.831838290163696481037 /* 0x0.d4f35aabd04a60006 */, +0.832965198041969556729 /* 0x0.d53d350c4be258002 */, +0.834093632565442222342 /* 0x0.d5872909aba050007 */, +0.835223595802037643865 /* 0x0.d5d136acd138e8006 */, +0.836355089820669306292 /* 0x0.d61b5dfe9f7780004 */, +0.837488116698010487424 /* 0x0.d6659f0801afa8005 */, +0.838622678508982644113 /* 0x0.d6aff9d1e147d8004 */, +0.839758777333464490056 /* 0x0.d6fa6e652d19e0000 */, +0.840896415254110962690 /* 0x0.d744fccad70d00003 */, +0.842035594355151628676 /* 0x0.d78fa50bd2c3b0000 */, +0.843176316724478125433 /* 0x0.d7da673117e730007 */, +0.844318584453106590905 /* 0x0.d8254343a19038003 */, +0.845462399634695271912 /* 0x0.d870394c6dbf30003 */, +0.846607764365415071965 /* 0x0.d8bb49547d37c0004 */, +0.847754680744707056494 /* 0x0.d9067364d45608003 */, +0.848903150873708822763 /* 0x0.d951b7867953b0006 */, +0.850053176859071113491 /* 0x0.d99d15c2787a30006 */, +0.851204760807439786431 /* 0x0.d9e88e21de11a0003 */, +0.852357904828824897169 /* 0x0.da3420adba1508003 */, +0.853512611037803181642 /* 0x0.da7fcd6f2184d8005 */, +0.854668881550406100980 /* 0x0.dacb946f2afaf8000 */, +0.855826718478671755185 /* 0x0.db1775b6e8ad48000 */, +0.856986123964844970247 /* 0x0.db63714f8e0818006 */, +0.858147100114499461478 /* 0x0.dbaf87422625b8000 */, +0.859309649060962410524 /* 0x0.dbfbb797daa460002 */, +0.860473772936213743282 /* 0x0.dc480259d3a710001 */, +0.861639473872910177676 /* 0x0.dc9467913a0f48006 */, +0.862806754008130227807 /* 0x0.dce0e7473b9b28003 */, +0.863975615481124226159 /* 0x0.dd2d8185086c20006 */, +0.865146060433749419813 /* 0x0.dd7a3653d38168005 */, +0.866318091005120138881 /* 0x0.ddc705bcccd628000 */, +0.867491709362415264210 /* 0x0.de13efc9434100004 */, +0.868666917636779056818 /* 0x0.de60f4825df9b8005 */, +0.869843717989716047624 /* 0x0.deae13f16599c0003 */, +0.871022112578215268471 /* 0x0.defb4e1f9dc388002 */, +0.872202103559697183859 /* 0x0.df48a3164a92f0001 */, +0.873383693097737778847 /* 0x0.df9612deb6e878007 */, +0.874566883362160263365 /* 0x0.dfe39d82348310001 */, +0.875751676517234511901 /* 0x0.e031430a0f0688000 */, +0.876938074732511840819 /* 0x0.e07f037f97e548001 */, +0.878126080186539592654 /* 0x0.e0ccdeec2a75e0006 */, +0.879315695055312818168 /* 0x0.e11ad5591f4078001 */, +0.880506921518618312932 /* 0x0.e168e6cfd2f880004 */, +0.881699761760385225541 /* 0x0.e1b71359a6df60003 */, +0.882894217964411143207 /* 0x0.e2055afffc1178000 */, +0.884090292325693805080 /* 0x0.e253bdcc3ffbb8001 */, +0.885287987031581180559 /* 0x0.e2a23bc7d7a1d8002 */, +0.886487304278189114386 /* 0x0.e2f0d4fc31ab80004 */, +0.887688246263368285778 /* 0x0.e33f8972bea8a8005 */, +0.888890815189881999840 /* 0x0.e38e5934f49010007 */, +0.890095013257492739835 /* 0x0.e3dd444c460bd0007 */, +0.891300842677948068626 /* 0x0.e42c4ac232f380000 */, +0.892508305659222567226 /* 0x0.e47b6ca036f8b8005 */, +0.893717404414979710310 /* 0x0.e4caa9efd40e58002 */, +0.894928141160697743242 /* 0x0.e51a02ba8e2610007 */, +0.896140518115016826430 /* 0x0.e5697709ecab90000 */, +0.897354537501434679237 /* 0x0.e5b906e77c61d0006 */, +0.898570201543732793877 /* 0x0.e608b25cca5ba8005 */, +0.899787512470129891014 /* 0x0.e6587973688ce8002 */, +0.901006472512270728537 /* 0x0.e6a85c34ecadb8000 */, +0.902227083902570559127 /* 0x0.e6f85aaaed4f20006 */, +0.903449348881299796343 /* 0x0.e74874df09a530003 */, +0.904673269686823378091 /* 0x0.e798aadadecba0007 */, +0.905898848559668845585 /* 0x0.e7e8fca80c3ee0001 */, +0.907126087750156795426 /* 0x0.e8396a503c3fe0005 */, +0.908354989505901100354 /* 0x0.e889f3dd1615b0002 */, +0.909585556079328783087 /* 0x0.e8da9958465228007 */, +0.910817789726044213523 /* 0x0.e92b5acb7d0578001 */, +0.912051692703457872481 /* 0x0.e97c38406c3c30003 */, +0.913287267274154990210 /* 0x0.e9cd31c0cbb370001 */, +0.914524515702244578108 /* 0x0.ea1e475654d540000 */, +0.915763440256158633982 /* 0x0.ea6f790ac5cc78001 */, +0.917004043205012497909 /* 0x0.eac0c6e7dd8448007 */, +0.918246326823137892807 /* 0x0.eb1230f760a428007 */, +0.919490293387826285200 /* 0x0.eb63b7431714a8007 */, +0.920735945178816406225 /* 0x0.ebb559d4cb6f30007 */, +0.921983284479243714322 /* 0x0.ec0718b64c0940002 */, +0.923232313574974705626 /* 0x0.ec58f3f16a3910002 */, +0.924483034755387955725 /* 0x0.ecaaeb8ffb3168005 */, +0.925735450311948926408 /* 0x0.ecfcff9bd67078000 */, +0.926989562542820610982 /* 0x0.ed4f301edad1a0007 */, +0.928245373740515189457 /* 0x0.eda17d22e0f9b0001 */, +0.929502886213858126045 /* 0x0.edf3e6b1d37d40001 */, +0.930762102264245716494 /* 0x0.ee466cd594c5c8005 */, +0.932023024199046146183 /* 0x0.ee990f980dcdb0005 */, +0.933285654329454095216 /* 0x0.eeebcf032bc470007 */, +0.934549994971191289044 /* 0x0.ef3eab20e0d3c0001 */, +0.935816048439005676599 /* 0x0.ef91a3fb1e1340004 */, +0.937083817055075818404 /* 0x0.efe4b99bdcc618006 */, +0.938353303143720007819 /* 0x0.f037ec0d1889b8000 */, +0.939624509028518128972 /* 0x0.f08b3b58cc2bb8006 */, +0.940897437041863904384 /* 0x0.f0dea788fc2a90000 */, +0.942172089516254085427 /* 0x0.f13230a7ad21b8003 */, +0.943448468787511540534 /* 0x0.f185d6bee754e0006 */, +0.944726577195256100890 /* 0x0.f1d999d8b73478005 */, +0.946006417082291717338 /* 0x0.f22d79ff2cb130000 */, +0.947287990793413858827 /* 0x0.f281773c59ec48007 */, +0.948571300678290207925 /* 0x0.f2d5919a566268001 */, +0.949856349088629370320 /* 0x0.f329c9233bceb0001 */, +0.951143138379053731954 /* 0x0.f37e1de1272068002 */, +0.952431670908847949364 /* 0x0.f3d28fde3a6728006 */, +0.953721949039916472305 /* 0x0.f4271f249a93f0001 */, +0.955013975135367898520 /* 0x0.f47bcbbe6deab0001 */, +0.956307751564417496418 /* 0x0.f4d095b5e16638004 */, +0.957603280698967163097 /* 0x0.f5257d1524f590006 */, +0.958900564911197350604 /* 0x0.f57a81e668d628000 */, +0.960199606581278120057 /* 0x0.f5cfa433e60e50007 */, +0.961500408088936442422 /* 0x0.f624e407d527a0007 */, +0.962802971817578789903 /* 0x0.f67a416c72b760006 */, +0.964107300155846558292 /* 0x0.f6cfbc6c011458004 */, +0.965413395493874504368 /* 0x0.f7255510c439a8002 */, +0.966721260225105960572 /* 0x0.f77b0b6503c5b8006 */, +0.968030896745834645873 /* 0x0.f7d0df730a7940005 */, +0.969342307458006424716 /* 0x0.f826d145294be8003 */, +0.970655494764855020231 /* 0x0.f87ce0e5b29fd8000 */, +0.971970461071268720958 /* 0x0.f8d30e5efaa8f0004 */, +0.973287208789983648852 /* 0x0.f92959bb5e3c08001 */, +0.974605740331924708124 /* 0x0.f97fc305383028004 */, +0.975926058115625383329 /* 0x0.f9d64a46ebb9f8004 */, +0.977248164559556209435 /* 0x0.fa2cef8adbfc68004 */, +0.978572062087848637573 /* 0x0.fa83b2db7253d0007 */, +0.979897753126343307191 /* 0x0.fada944319fda0005 */, +0.981225240104636631254 /* 0x0.fb3193cc425870002 */, +0.982554525455618277276 /* 0x0.fb88b1815e61d0003 */, +0.983885611617111077747 /* 0x0.fbdfed6ce683e0007 */, +0.985218501026348891812 /* 0x0.fc3747995282f8006 */, +0.986553196127724962867 /* 0x0.fc8ec0112202a0005 */, +0.987889699367056062238 /* 0x0.fce656ded63710002 */, +0.989228013193998778636 /* 0x0.fd3e0c0cf48d50005 */, +0.990568140061241164686 /* 0x0.fd95dfa605c7b0003 */, +0.991910082424819927754 /* 0x0.fdedd1b4965710004 */, +0.993253842749249660216 /* 0x0.fe45e2433bfea0000 */, +0.994599423484053835071 /* 0x0.fe9e115c7c05f0005 */, +0.995946827107488830167 /* 0x0.fef65f0afb4c28006 */, +0.997296056085008264529 /* 0x0.ff4ecb59509cc8001 */, +0.998647112892057764479 /* 0x0.ffa756521dbfd0007 */, +1.000000000000000000000 /* 0x1.00000000000000000 */, +1.001354719891689004659 /* 0x1.0058c86da14aa0005 */, +1.002711275050312211844 /* 0x1.00b1afa5abead0003 */, +1.004069667960743483835 /* 0x1.010ab5b2cc0660009 */, +1.005429901112333324093 /* 0x1.0163da9fb2af30008 */, +1.006791976999887428009 /* 0x1.01bd1e7716f6a0008 */, +1.008155898118476168101 /* 0x1.02168143b03890006 */, +1.009521666967782227439 /* 0x1.027003103ae320002 */, +1.010889286051850133326 /* 0x1.02c9a3e7783030002 */, +1.012258757875921233497 /* 0x1.032363d42aaa8000e */, +1.013630084952214405194 /* 0x1.037d42e11c88d0000 */, +1.015003269791313389451 /* 0x1.03d741191635a0001 */, +1.016378314911229763267 /* 0x1.04315e86e84630008 */, +1.017755222831652872635 /* 0x1.048b9b35652800002 */, +1.019133996077934645224 /* 0x1.04e5f72f65827000b */, +1.020514637175266248212 /* 0x1.0540727fc1cfa0006 */, +1.021897148653734488385 /* 0x1.059b0d3157ebb0002 */, +1.023281533050062419584 /* 0x1.05f5c74f0cfeb0002 */, +1.024667792897328677539 /* 0x1.0650a0e3c22ee0003 */, +1.026055930738840826806 /* 0x1.06ab99fa63e1b0008 */, +1.027445949118511947550 /* 0x1.0706b29ddf2700009 */, +1.028837850584049418178 /* 0x1.0761ead9253ab0009 */, +1.030231637685799839262 /* 0x1.07bd42b72a3f80008 */, +1.031627312979383592802 /* 0x1.0818ba42e824a000c */, +1.033024879021186448496 /* 0x1.0874518759b0b0008 */, +1.034424338374263729911 /* 0x1.08d0088f80ffa0006 */, +1.035825693601787333992 /* 0x1.092bdf66604e30005 */, +1.037228947273990842283 /* 0x1.0987d617019cd000a */, +1.038634101961269928846 /* 0x1.09e3ecac6f199000f */, +1.040041160239590700707 /* 0x1.0a402331b91270002 */, +1.041450124688240164200 /* 0x1.0a9c79b1f37c3000b */, +1.042860997889083929381 /* 0x1.0af8f038352160000 */, +1.044273782427270314011 /* 0x1.0b5586cf986890006 */, +1.045688480893644856116 /* 0x1.0bb23d833dfbf0006 */, +1.047105095879385272564 /* 0x1.0c0f145e46e330007 */, +1.048523629981608529302 /* 0x1.0c6c0b6bdaadc000f */, +1.049944085800634585634 /* 0x1.0cc922b72470a000f */, +1.051366465939483019223 /* 0x1.0d265a4b5238b0007 */, +1.052790773004648849929 /* 0x1.0d83b23395e510002 */, +1.054217009607077093512 /* 0x1.0de12a7b263970006 */, +1.055645178360430591625 /* 0x1.0e3ec32d3cf680000 */, +1.057075281882416506511 /* 0x1.0e9c7c55184f5000e */, +1.058507322794714378170 /* 0x1.0efa55fdfad51000a */, +1.059941303721639416236 /* 0x1.0f58503329fed0003 */, +1.061377227289284297385 /* 0x1.0fb66affed37f0000 */, +1.062815096132297298980 /* 0x1.1014a66f95540000c */, +1.064254912884593951029 /* 0x1.1073028d725850007 */, +1.065696680185205469411 /* 0x1.10d17f64d9ea2000b */, +1.067140400676658718053 /* 0x1.11301d012586a0007 */, +1.068586077004890055886 /* 0x1.118edb6db26ab0003 */, +1.070033711820396415998 /* 0x1.11edbab5e2d6e000b */, +1.071483307775789262099 /* 0x1.124cbae51b5ef0001 */, +1.072934867526001312439 /* 0x1.12abdc06c3240000c */, +1.074388393734249103080 /* 0x1.130b1e264a62e0005 */, +1.075843889063253344684 /* 0x1.136a814f20ccd0003 */, +1.077301356179926061823 /* 0x1.13ca058cbaaed000b */, +1.078760797756675327056 /* 0x1.1429aaea9260e000e */, +1.080222216468626150775 /* 0x1.148971742537c0009 */, +1.081685614993597610617 /* 0x1.14e95934f37e8000b */, +1.083150996013011013776 /* 0x1.1549623881762000d */, +1.084618362213087383633 /* 0x1.15a98c8a58a6a000b */, +1.086087716284427351384 /* 0x1.1609d8360768c0008 */, +1.087559060917626885283 /* 0x1.166a45471c13f0008 */, +1.089032398810997337465 /* 0x1.16cad3c92d7b50009 */, +1.090507732647478578212 /* 0x1.172b83c7c18b5000f */, +1.091985065182095926460 /* 0x1.178c554ead72a000c */, +1.093464399073070136880 /* 0x1.17ed48695befe000c */, +1.094945737045367906172 /* 0x1.184e5d23812500007 */, +1.096429081816546080591 /* 0x1.18af9388c90e40005 */, +1.097914436104650892651 /* 0x1.1910eba4e031a0001 */, +1.099401802629782043408 /* 0x1.19726583755720003 */, +1.100891184121537858001 /* 0x1.19d4013041b860007 */, +1.102382583308144647940 /* 0x1.1a35beb6fd0cd0007 */, +1.103876002922312915544 /* 0x1.1a979e2363fa10000 */, +1.105371445702084232160 /* 0x1.1af99f8139025000e */, +1.106868914387219016199 /* 0x1.1b5bc2dc408b9000e */, +1.108368411723785085252 /* 0x1.1bbe084045eb30002 */, +1.109869940458469095340 /* 0x1.1c206fb91524c000e */, +1.111373503344554869449 /* 0x1.1c82f952817cc0001 */, +1.112879103137133007859 /* 0x1.1ce5a51860344000f */, +1.114386742595953938610 /* 0x1.1d4873168babf000e */, +1.115896424484008608911 /* 0x1.1dab6358e1d4a000f */, +1.117408151567338414664 /* 0x1.1e0e75eb43f9c000c */, +1.118921926613465345265 /* 0x1.1e71aad995078000f */, +1.120437752409564780022 /* 0x1.1ed5022fcd8600003 */, +1.121955631720569668277 /* 0x1.1f387bf9cd88b0000 */, +1.123475567332998359439 /* 0x1.1f9c18438cdec000a */, +1.124997562033035469759 /* 0x1.1fffd71902f970002 */, +1.126521618608448571713 /* 0x1.2063b88629079000e */, +1.128047739853580200284 /* 0x1.20c7bc96ff72a0002 */, +1.129575928566289189112 /* 0x1.212be3578a81e0006 */, +1.131106187546149888259 /* 0x1.21902cd3d05f70007 */, +1.132638519598779369743 /* 0x1.21f49917ddda5000c */, +1.134172927531616359481 /* 0x1.2259282fc1c24000e */, +1.135709414157753949251 /* 0x1.22bdda27911e90007 */, +1.137247982292643566662 /* 0x1.2322af0b638e60007 */, +1.138788634756517259562 /* 0x1.2387a6e755f270000 */, +1.140331374372893558110 /* 0x1.23ecc1c788c890006 */, +1.141876203969685699176 /* 0x1.2451ffb821639000c */, +1.143423126377846266197 /* 0x1.24b760c5486dc0009 */, +1.144972144431494420774 /* 0x1.251ce4fb2a0cc0005 */, +1.146523260971646252006 /* 0x1.25828c65f9fb8000d */, +1.148076478839068270690 /* 0x1.25e85711ebaeb0000 */, +1.149631800883562204903 /* 0x1.264e450b3c8a30008 */, +1.151189229953253789786 /* 0x1.26b4565e281a20003 */, +1.152748768902654319399 /* 0x1.271a8b16f0f000002 */, +1.154310420590433317050 /* 0x1.2780e341de2fc0001 */, +1.155874187878668246681 /* 0x1.27e75eeb3abc90007 */, +1.157440073633736243899 /* 0x1.284dfe1f5633e000a */, +1.159008080725518974322 /* 0x1.28b4c0ea840d90001 */, +1.160578212048386514965 /* 0x1.291ba75932ae60000 */, +1.162150470417516290340 /* 0x1.2982b177796850008 */, +1.163724858777502646494 /* 0x1.29e9df51fdd900001 */, +1.165301379991388053320 /* 0x1.2a5130f50bf34000e */, +1.166880036952526289469 /* 0x1.2ab8a66d10fdc0008 */, +1.168460832550151540268 /* 0x1.2b203fc675b7a000a */, +1.170043769683112966389 /* 0x1.2b87fd0dad7260008 */, +1.171628851252754177681 /* 0x1.2befde4f2e3da000d */, +1.173216080163546060084 /* 0x1.2c57e397719940002 */, +1.174805459325657830448 /* 0x1.2cc00cf2f7491000c */, +1.176396991650083379037 /* 0x1.2d285a6e3ff90000b */, +1.177990680055698513602 /* 0x1.2d90cc15d4ff90005 */, +1.179586527463262646306 /* 0x1.2df961f641c57000c */, +1.181184536796979545103 /* 0x1.2e621c1c157cd000d */, +1.182784710984701836994 /* 0x1.2ecafa93e35af0004 */, +1.184387052960675701386 /* 0x1.2f33fd6a459cb0000 */, +1.185991565661414393112 /* 0x1.2f9d24abd8fd1000e */, +1.187598252026902612178 /* 0x1.300670653e083000a */, +1.189207115003001469262 /* 0x1.306fe0a31bc040008 */, +1.190818157535919796833 /* 0x1.30d9757219895000e */, +1.192431382587621380206 /* 0x1.31432edef01a1000f */, +1.194046793097208292195 /* 0x1.31ad0cf63f0630008 */, +1.195664392040319823392 /* 0x1.32170fc4ce0db000c */, +1.197284182375793593084 /* 0x1.32813757527750005 */, +1.198906167074650808198 /* 0x1.32eb83ba8eef3000f */, +1.200530349107333139048 /* 0x1.3355f4fb457e5000d */, +1.202156731453099647353 /* 0x1.33c08b2641df9000c */, +1.203785317090505513368 /* 0x1.342b46484f07b0005 */, +1.205416109005122526928 /* 0x1.3496266e3fa270005 */, +1.207049110184904572310 /* 0x1.35012ba4e8fa10000 */, +1.208684323627194912036 /* 0x1.356c55f92aabb0004 */, +1.210321752322854882437 /* 0x1.35d7a577dd33f0004 */, +1.211961399276747286580 /* 0x1.36431a2de8748000d */, +1.213603267492579629347 /* 0x1.36aeb4283309e000c */, +1.215247359985374142610 /* 0x1.371a7373b00160000 */, +1.216893679753690671322 /* 0x1.3786581d404e90000 */, +1.218542229828181611183 /* 0x1.37f26231e82e4000c */, +1.220193013225231215567 /* 0x1.385e91be9c2d20002 */, +1.221846032973555429280 /* 0x1.38cae6d05e66f0000 */, +1.223501292099485437962 /* 0x1.393761742e5830001 */, +1.225158793636904830441 /* 0x1.39a401b713cb3000e */, +1.226818540625497444577 /* 0x1.3a10c7a61ceae0007 */, +1.228480536107136034131 /* 0x1.3a7db34e5a4a50003 */, +1.230144783126481566885 /* 0x1.3aeac4bcdf8d60001 */, +1.231811284734168454619 /* 0x1.3b57fbfec6e950008 */, +1.233480043984379381835 /* 0x1.3bc559212e7a2000f */, +1.235151063936380300149 /* 0x1.3c32dc3139f2a0004 */, +1.236824347652524913647 /* 0x1.3ca0853c106ac000e */, +1.238499898199571624970 /* 0x1.3d0e544eddd240003 */, +1.240177718649636107175 /* 0x1.3d7c4976d3fcd0000 */, +1.241857812073360767273 /* 0x1.3dea64c1231f70004 */, +1.243540181554270152039 /* 0x1.3e58a63b099920005 */, +1.245224830175077013244 /* 0x1.3ec70df1c4e46000e */, +1.246911761022835740725 /* 0x1.3f359bf29741c000e */, +1.248600977188942806639 /* 0x1.3fa4504ac7b800009 */, +1.250292481770148400634 /* 0x1.40132b07a330d000a */, +1.251986277866492969263 /* 0x1.40822c367a340000b */, +1.253682368581898742876 /* 0x1.40f153e4a18e0000d */, +1.255380757024939564249 /* 0x1.4160a21f73289000d */, +1.257081446308726757662 /* 0x1.41d016f44deaa000c */, +1.258784439550028944083 /* 0x1.423fb27094c090008 */, +1.260489739869405489991 /* 0x1.42af74a1aec1c0006 */, +1.262197350394008266193 /* 0x1.431f5d950a453000c */, +1.263907274252603851764 /* 0x1.438f6d58176860004 */, +1.265619514578811388761 /* 0x1.43ffa3f84b9eb000d */, +1.267334074511444086425 /* 0x1.44700183221180008 */, +1.269050957191869555296 /* 0x1.44e0860618b930006 */, +1.270770165768063009230 /* 0x1.4551318eb4d20000e */, +1.272491703389059036805 /* 0x1.45c2042a7cc26000b */, +1.274215573211836316547 /* 0x1.4632fde6ffacd000d */, +1.275941778396075143580 /* 0x1.46a41ed1cfac40001 */, +1.277670322103555911043 /* 0x1.471566f8812ac0000 */, +1.279401207505722393185 /* 0x1.4786d668b33260005 */, +1.281134437771823675369 /* 0x1.47f86d3002637000a */, +1.282870016078732078362 /* 0x1.486a2b5c13c00000e */, +1.284607945607987078432 /* 0x1.48dc10fa916bd0004 */, +1.286348229545787758022 /* 0x1.494e1e192aaa30007 */, +1.288090871080605159846 /* 0x1.49c052c5913df000c */, +1.289835873406902644341 /* 0x1.4a32af0d7d8090002 */, +1.291583239722392528754 /* 0x1.4aa532feab5e10002 */, +1.293332973229098792374 /* 0x1.4b17dea6db8010008 */, +1.295085077135345708087 /* 0x1.4b8ab213d57d9000d */, +1.296839554650994097442 /* 0x1.4bfdad53629e10003 */, +1.298596408992440220988 /* 0x1.4c70d0735358a000d */, +1.300355643380135983739 /* 0x1.4ce41b817c99e0001 */, +1.302117261036232376282 /* 0x1.4d578e8bb52cb0003 */, +1.303881265192249561154 /* 0x1.4dcb299fde2920008 */, +1.305647659079073541490 /* 0x1.4e3eeccbd7f4c0003 */, +1.307416445934474813521 /* 0x1.4eb2d81d8a86f000b */, +1.309187629001237640529 /* 0x1.4f26eba2e35a5000e */, +1.310961211525240921493 /* 0x1.4f9b2769d35090009 */, +1.312737196755087820678 /* 0x1.500f8b804e4a30000 */, +1.314515587949291131086 /* 0x1.508417f4530d00009 */, +1.316296388365203462468 /* 0x1.50f8ccd3df1840003 */, +1.318079601265708777911 /* 0x1.516daa2cf60020002 */, +1.319865229921343141607 /* 0x1.51e2b00da3c2b0007 */, +1.321653277603506371251 /* 0x1.5257de83f5512000d */, +1.323443747588034513690 /* 0x1.52cd359dfc7d5000e */, +1.325236643161341820781 /* 0x1.5342b569d6baa000f */, +1.327031967602244177939 /* 0x1.53b85df59921b0000 */, +1.328829724206201046165 /* 0x1.542e2f4f6b17e0006 */, +1.330629916266568235675 /* 0x1.54a4298571b27000e */, +1.332432547083447937938 /* 0x1.551a4ca5d97190009 */, +1.334237619959296017340 /* 0x1.559098bed16bf0008 */, +1.336045138203900251029 /* 0x1.56070dde90c800000 */, +1.337855105129210686631 /* 0x1.567dac13510cd0009 */, +1.339667524053662184301 /* 0x1.56f4736b52e2c000c */, +1.341482398296830025383 /* 0x1.576b63f4d8333000f */, +1.343299731186792467254 /* 0x1.57e27dbe2c40e0003 */, +1.345119526053918823702 /* 0x1.5859c0d59cd37000f */, +1.346941786233264881662 /* 0x1.58d12d497cd9a0005 */, +1.348766515064854010261 /* 0x1.5948c32824b87000c */, +1.350593715891792223641 /* 0x1.59c0827ff03890007 */, +1.352423392064920459908 /* 0x1.5a386b5f43a3e0006 */, +1.354255546937278120764 /* 0x1.5ab07dd485af1000c */, +1.356090183865519494030 /* 0x1.5b28b9ee21085000f */, +1.357927306213322804534 /* 0x1.5ba11fba8816e000b */, +1.359766917346459269620 /* 0x1.5c19af482f8f2000f */, +1.361609020638567812980 /* 0x1.5c9268a594cc00004 */, +1.363453619463660171403 /* 0x1.5d0b4be135916000c */, +1.365300717204201985683 /* 0x1.5d84590998eeb0005 */, +1.367150317245710233754 /* 0x1.5dfd902d494e40001 */, +1.369002422974674892971 /* 0x1.5e76f15ad22c40008 */, +1.370857037789471544224 /* 0x1.5ef07ca0cc166000b */, +1.372714165088220639199 /* 0x1.5f6a320dcf5280006 */, +1.374573808273481745378 /* 0x1.5fe411b0790800009 */, +1.376435970755022220096 /* 0x1.605e1b976e4b1000e */, +1.378300655944092456600 /* 0x1.60d84fd155d15000e */, +1.380167867259843417228 /* 0x1.6152ae6cdf0030003 */, +1.382037608124419003675 /* 0x1.61cd3778bc879000d */, +1.383909881963391264069 /* 0x1.6247eb03a4dc40009 */, +1.385784692209972801544 /* 0x1.62c2c91c56d9b0002 */, +1.387662042298923203992 /* 0x1.633dd1d1930ec0001 */, +1.389541935670444372533 /* 0x1.63b90532200630004 */, +1.391424375772021271329 /* 0x1.6434634ccc4cc0007 */, +1.393309366052102982208 /* 0x1.64afec30677e90008 */, +1.395196909966106124701 /* 0x1.652b9febc8e0f000d */, +1.397087010973788290271 /* 0x1.65a77e8dcc7f10004 */, +1.398979672539331309267 /* 0x1.66238825534170000 */, +1.400874898129892187656 /* 0x1.669fbcc1415600008 */, +1.402772691220124823310 /* 0x1.671c1c708328e000a */, +1.404673055288671035301 /* 0x1.6798a7420988b000d */, +1.406575993818903302975 /* 0x1.68155d44ca77a000f */, +1.408481510297352468121 /* 0x1.68923e87bf70e000a */, +1.410389608216942924956 /* 0x1.690f4b19e8f74000c */, +1.412300291075172076232 /* 0x1.698c830a4c94c0008 */ +}; +#define S (1.0/4503599627370496.0) /* 2^-52 */ +static const float exp2_deltatable[512] = { + 11527*S, -963*S, 884*S, -781*S, -2363*S, -3441*S, 123*S, 526*S, + -6*S, 1254*S, -1138*S, 1519*S, 1576*S, -65*S, 1040*S, 793*S, + -1662*S, -5063*S, -387*S, 968*S, -941*S, 984*S, -2856*S, -545*S, + 495*S, -5246*S, -2109*S, 1281*S, 2075*S, 909*S, -1642*S,-78233*S, +-31653*S, -265*S, 130*S, 430*S, 2482*S, -742*S, 1616*S, -2213*S, + -519*S, 20*S, -3134*S,-13981*S, 1343*S, -1740*S, 247*S, 1679*S, + -1097*S, 3131*S, 871*S, -1480*S, 1936*S, -1827*S, 17325*S, 528*S, + -322*S, 1404*S, -152*S, -1845*S, -212*S, 2639*S, -476*S, 2960*S, + -962*S, -1012*S, -1231*S, 3030*S, 1659*S, -486*S, 2154*S, 1728*S, + -2793*S, 699*S, -1560*S, -2125*S, 2156*S, 142*S, -1888*S, 4426*S, +-13443*S, 1970*S, -50*S, 1771*S,-43399*S, 4979*S, -2448*S, -370*S, + 1414*S, 1075*S, 232*S, 206*S, 873*S, 2141*S, 2970*S, 1279*S, + -2331*S, 336*S, -2595*S, 753*S, -3384*S, -616*S, 89*S, -818*S, + 5755*S, -241*S, -528*S, -661*S, -3777*S, -354*S, 250*S, 3881*S, + 2632*S, -2131*S, 2565*S, -316*S, 1746*S, -2541*S, -1324*S, -50*S, + 2564*S, -782*S, 1176*S, 6452*S, -1002*S, 1288*S, 336*S, -185*S, + 3063*S, 3784*S, 2169*S, 686*S, 328*S, -400*S, 312*S, -4517*S, + -1457*S, 1046*S, -1530*S, -685*S, 1328*S,-49815*S, -895*S, 1063*S, + -2091*S, -672*S, -1710*S, -665*S, 1545*S, 1819*S,-45265*S, 3548*S, + -554*S, -568*S, 4752*S, -1907*S,-13738*S, 675*S, 9611*S, -1115*S, + -815*S, 408*S, -1281*S, -937*S,-16376*S, -4772*S, -1440*S, 992*S, + 788*S, 10364*S, -1602*S, -661*S, -1783*S, -265*S, -20*S, -3781*S, + -861*S, -345*S, -994*S, 1364*S, -5339*S, 1620*S, 9390*S, -1066*S, + -305*S, -170*S, 175*S, 2461*S, -490*S, -769*S, -1450*S, 3315*S, + 2418*S, -45*S, -852*S, -1295*S, -488*S, -96*S, 1142*S, -2639*S, + 7905*S, -9306*S, -3859*S, 760*S, 1057*S, -1570*S, 3977*S, 209*S, + -514*S, 7151*S, 1646*S, 627*S, 599*S, -774*S, -1468*S, 633*S, + -473*S, 851*S, 2406*S, 143*S, 74*S, 4260*S, 1177*S, -913*S, + 2670*S, -3298*S, -1662*S, -120*S, -3264*S, -2148*S, 410*S, 2078*S, + -2098*S, -926*S, 3580*S, -1289*S, 2450*S, -1158*S, 907*S, -590*S, + 986*S, 1801*S, 1145*S, -1677*S, 3455*S, 956*S, 710*S, 144*S, + 153*S, -255*S, -1898*S, 28102*S, 2748*S, 1194*S, -3009*S, 7076*S, + 0*S, -2720*S, 711*S, 1225*S, -3034*S, -473*S, 378*S, -1046*S, + 962*S, -2006*S, 4647*S, 3206*S, 1769*S, -2665*S, 1254*S, 2025*S, + -2430*S, 6193*S, 1224*S, -856*S, -1592*S, -325*S, -1521*S, 1827*S, + -264*S, 2403*S, -1065*S, 967*S, -681*S, -2106*S, -474*S, 1333*S, + -893*S, 2296*S, 592*S, -1220*S, -326*S, 990*S, 139*S, 206*S, + -779*S, -1683*S, 1238*S, 6098*S, 136*S, 1197*S, 790*S, -107*S, + -1004*S, -2449*S, 939*S, 5568*S, 156*S, 1812*S, 2792*S, -1094*S, + -2677*S, -251*S, 2297*S, 943*S, -1329*S, 2883*S, -853*S, -2626*S, +-105929*S, -6552*S, 1095*S, -1508*S, 1003*S, 5039*S, -2600*S, -749*S, + 1790*S, 890*S, 2016*S, -1073*S, 624*S, -2084*S, -1536*S, -1330*S, + 358*S, 2444*S, -179*S,-25759*S, -243*S, -552*S, -124*S, 3766*S, + 1192*S, -1614*S, 6*S, -1227*S, 345*S, -981*S, -295*S, -1006*S, + -995*S, -1195*S, 706*S, 2512*S, -1758*S, -734*S, -6286*S, -922*S, + 1530*S, 1542*S, 1223*S, 61*S, -83*S, 522*S,116937*S, -914*S, + -418*S, -7339*S, 249*S, -520*S, -762*S, 426*S, -505*S, 2664*S, + -1093*S, -1035*S, 2130*S, 4878*S, 1982*S, 1551*S, 2304*S, 193*S, + 1532*S, -7268*S, 24357*S, 531*S, 2676*S, -1170*S, 1465*S, -1917*S, + 2143*S, 1466*S, -7*S, -7300*S, 3297*S, -1197*S, -289*S, -1548*S, + 26226*S, 4401*S, 4123*S, -1588*S, 4243*S, 4069*S, -1276*S, -2010*S, + 1407*S, 1478*S, 488*S, -2366*S, -2909*S, -2534*S, -1285*S, 7095*S, + -645*S, -2089*S, -944*S, -40*S, -1363*S, -833*S, 917*S, 1609*S, + 1286*S, 1677*S, 1613*S, -2295*S, -1248*S, 40*S, 26*S, 2038*S, + 698*S, 2675*S, -1755*S, -3522*S, -1614*S, -6111*S, 270*S, 1822*S, + -234*S, -2844*S, -1201*S, -830*S, 1193*S, 2354*S, 47*S, 1522*S, + -78*S, -640*S, 2425*S, -1596*S, 1563*S, 1169*S, -1006*S, -83*S, + 2362*S, -3521*S, -314*S, 1814*S, -1751*S, 305*S, 1715*S, -3741*S, + 7847*S, 1291*S, 1206*S, 36*S, 1397*S, -1419*S, -1194*S, -2014*S, + 1742*S, -578*S, -207*S, 875*S, 1539*S, 2826*S, -1165*S, -909*S, + 1849*S, 927*S, 2018*S, -981*S, 1637*S, -463*S, 905*S, 6618*S, + 400*S, 630*S, 2614*S, 900*S, 2323*S, -1094*S, -1858*S, -212*S, + -2069*S, 747*S, 1845*S, -1450*S, 444*S, -213*S, -438*S, 1158*S, + 4738*S, 2497*S, -370*S, -2016*S, -518*S, -1160*S, -1510*S, 123*S +}; +/* Maximum magnitude in above table: 116937 */ +#undef S diff --git a/src/system/libroot/posix/glibc/arch/generic/t_exp2f.h b/src/system/libroot/posix/glibc/arch/generic/t_exp2f.h new file mode 100644 index 0000000000..f4b94b0498 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/t_exp2f.h @@ -0,0 +1,352 @@ +/* Accurate tables for exp2f(). + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Geoffrey Keating + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This table has the property that, for all integers -128 <= i <= 127, + exp(i/256.0 + __exp2f_deltatable[i-128]) == __exp2f_atable[i+128] + r + for some -2^-35 < r < 2^-35 (abs(r) < 2^-36 if i <= 0); and that + __exp2f_deltatable[i+128] == t * 2^-30 + for integer t so that abs(t) <= 43447 * 2^0. */ + +#define W30 (9.31322575e-10) +static const float __exp2f_deltatable[256] = { + -810*W30, 283*W30, -1514*W30, 1304*W30, + -1148*W30, -98*W30, -744*W30, -156*W30, + -419*W30, -155*W30, 474*W30, 167*W30, + -1984*W30, -826*W30, 692*W30, 781*W30, + -578*W30, -411*W30, -129*W30, -1500*W30, + 654*W30, -141*W30, -816*W30, -53*W30, + 148*W30, 493*W30, -2214*W30, 760*W30, + 260*W30, 750*W30, -1300*W30, 1424*W30, + -1445*W30, -339*W30, -680*W30, -349*W30, + -922*W30, 531*W30, 193*W30, -2892*W30, + 290*W30, -2145*W30, -276*W30, 485*W30, + -695*W30, 215*W30, -7093*W30, 412*W30, + -4596*W30, 367*W30, 592*W30, -615*W30, + -97*W30, -1066*W30, 972*W30, -226*W30, + -625*W30, -374*W30, -5647*W30, -180*W30, + 20349*W30, -447*W30, 111*W30, -4164*W30, + -87*W30, -21*W30, -251*W30, 66*W30, + -517*W30, 2093*W30, -263*W30, 182*W30, + -601*W30, 475*W30, -483*W30, -1251*W30, + -373*W30, 1471*W30, -92*W30, -215*W30, + -97*W30, -190*W30, 0*W30, -290*W30, + -2647*W30, 1940*W30, -582*W30, 28*W30, + 833*W30, 1493*W30, 34*W30, 321*W30, + 3327*W30, -35*W30, 177*W30, -135*W30, + -796*W30, -428*W30, 129*W30, 9332*W30, + -12*W30, -69*W30, -1743*W30, 6508*W30, + -60*W30, 359*W30, 43447*W30, 15*W30, + -23*W30, -305*W30, -375*W30, -652*W30, + 667*W30, 269*W30, -1575*W30, 185*W30, + -329*W30, 200*W30, 6002*W30, 163*W30, + -647*W30, 19*W30, -603*W30, -755*W30, + 742*W30, -438*W30, 3587*W30, 2560*W30, + 0*W30, -520*W30, -241*W30, -299*W30, + -1270*W30, -991*W30, -1138*W30, 255*W30, + -1192*W30, 1722*W30, 1023*W30, 3700*W30, + -1388*W30, -1551*W30, -2549*W30, 27*W30, + 282*W30, 673*W30, 113*W30, 1561*W30, + 72*W30, 873*W30, 87*W30, -395*W30, + -433*W30, 629*W30, 3440*W30, -284*W30, + -592*W30, -103*W30, -46*W30, -3844*W30, + 1712*W30, 303*W30, 1555*W30, -631*W30, + -1400*W30, -961*W30, -854*W30, -276*W30, + 407*W30, 833*W30, -345*W30, -1501*W30, + 121*W30, -1581*W30, 400*W30, 150*W30, + 1224*W30, -139*W30, -563*W30, 879*W30, + 933*W30, 2939*W30, 788*W30, 211*W30, + 530*W30, -192*W30, 706*W30, -13347*W30, + 1065*W30, 3*W30, 111*W30, -208*W30, + -360*W30, -532*W30, -291*W30, 483*W30, + 987*W30, -33*W30, -1373*W30, -166*W30, + -1174*W30, -3955*W30, 1601*W30, -280*W30, + 1405*W30, 600*W30, -1659*W30, -23*W30, + 390*W30, 449*W30, 570*W30, -13143*W30, + -9*W30, -1646*W30, 1201*W30, 294*W30, + 2181*W30, -1173*W30, 1388*W30, -4504*W30, + 190*W30, -2304*W30, 211*W30, 239*W30, + 48*W30, -817*W30, 1018*W30, 1828*W30, + -663*W30, 1408*W30, 408*W30, -36*W30, + 1295*W30, -230*W30, 1341*W30, 9*W30, + 40*W30, 705*W30, 186*W30, 376*W30, + 557*W30, 5866*W30, 363*W30, -1558*W30, + 718*W30, 669*W30, 1369*W30, -2972*W30, + -468*W30, -121*W30, -219*W30, 667*W30, + 29954*W30, 366*W30, 48*W30, -203*W30 +}; + +static const float __exp2f_atable[256] /* __attribute__((mode(SF))) */ = { + 0.707106411447, /* 0x0.b504ecfff */ + 0.709024071690, /* 0x0.b58299fff */ + 0.710945606239, /* 0x0.b60088000 */ + 0.712874472142, /* 0x0.b67ef1000 */ + 0.714806139464, /* 0x0.b6fd88fff */ + 0.716744661340, /* 0x0.b77c94000 */ + 0.718687653549, /* 0x0.b7fbea000 */ + 0.720636486992, /* 0x0.b87ba1fff */ + 0.722590208040, /* 0x0.b8fbabfff */ + 0.724549472323, /* 0x0.b97c12fff */ + 0.726514220228, /* 0x0.b9fcd5fff */ + 0.728483855735, /* 0x0.ba7deb000 */ + 0.730457961549, /* 0x0.baff4afff */ + 0.732438981522, /* 0x0.bb811efff */ + 0.734425544748, /* 0x0.bc0350000 */ + 0.736416816713, /* 0x0.bc85d0000 */ + 0.738412797450, /* 0x0.bd089efff */ + 0.740414917465, /* 0x0.bd8bd4fff */ + 0.742422521111, /* 0x0.be0f66fff */ + 0.744434773914, /* 0x0.be9346fff */ + 0.746454179287, /* 0x0.bf179f000 */ + 0.748477637755, /* 0x0.bf9c3afff */ + 0.750506639473, /* 0x0.c02133fff */ + 0.752541840064, /* 0x0.c0a694fff */ + 0.754582285889, /* 0x0.c12c4e000 */ + 0.756628334525, /* 0x0.c1b265000 */ + 0.758678436269, /* 0x0.c238bffff */ + 0.760736882681, /* 0x0.c2bfa6fff */ + 0.762799203401, /* 0x0.c346cf000 */ + 0.764867603790, /* 0x0.c3ce5d000 */ + 0.766940355298, /* 0x0.c45633fff */ + 0.769021093841, /* 0x0.c4de90fff */ + 0.771104693409, /* 0x0.c5671dfff */ + 0.773195922364, /* 0x0.c5f02afff */ + 0.775292098512, /* 0x0.c6798afff */ + 0.777394294745, /* 0x0.c70350000 */ + 0.779501736166, /* 0x0.c78d6d000 */ + 0.781615912910, /* 0x0.c817fafff */ + 0.783734917628, /* 0x0.c8a2d9fff */ + 0.785858273516, /* 0x0.c92e02000 */ + 0.787990570071, /* 0x0.c9b9c0000 */ + 0.790125787245, /* 0x0.ca45aefff */ + 0.792268991467, /* 0x0.cad223fff */ + 0.794417440881, /* 0x0.cb5ef0fff */ + 0.796570718287, /* 0x0.cbec0efff */ + 0.798730909811, /* 0x0.cc79a0fff */ + 0.800892710672, /* 0x0.cd074dfff */ + 0.803068041795, /* 0x0.cd95ddfff */ + 0.805242776881, /* 0x0.ce2464000 */ + 0.807428598393, /* 0x0.ceb3a3fff */ + 0.809617877002, /* 0x0.cf431dfff */ + 0.811812341211, /* 0x0.cfd2eefff */ + 0.814013659956, /* 0x0.d06333000 */ + 0.816220164311, /* 0x0.d0f3ce000 */ + 0.818434238424, /* 0x0.d184e7fff */ + 0.820652604094, /* 0x0.d21649fff */ + 0.822877407074, /* 0x0.d2a818000 */ + 0.825108587751, /* 0x0.d33a51000 */ + 0.827342867839, /* 0x0.d3ccbdfff */ + 0.829588949684, /* 0x0.d45ff1000 */ + 0.831849217401, /* 0x0.d4f411fff */ + 0.834093391880, /* 0x0.d58724fff */ + 0.836355149750, /* 0x0.d61b5f000 */ + 0.838620424257, /* 0x0.d6afd3fff */ + 0.840896368027, /* 0x0.d744fc000 */ + 0.843176305293, /* 0x0.d7da66fff */ + 0.845462262643, /* 0x0.d87037000 */ + 0.847754716864, /* 0x0.d90673fff */ + 0.850052893157, /* 0x0.d99d10fff */ + 0.852359056469, /* 0x0.da3433fff */ + 0.854668736446, /* 0x0.dacb91fff */ + 0.856986224651, /* 0x0.db6373000 */ + 0.859309315673, /* 0x0.dbfbb1fff */ + 0.861639738080, /* 0x0.dc946bfff */ + 0.863975346095, /* 0x0.dd2d7d000 */ + 0.866317391394, /* 0x0.ddc6f9fff */ + 0.868666708472, /* 0x0.de60f1000 */ + 0.871022939695, /* 0x0.defb5c000 */ + 0.873383641229, /* 0x0.df9611fff */ + 0.875751554968, /* 0x0.e03141000 */ + 0.878126025200, /* 0x0.e0ccde000 */ + 0.880506813521, /* 0x0.e168e4fff */ + 0.882894217966, /* 0x0.e2055afff */ + 0.885287821299, /* 0x0.e2a239000 */ + 0.887686729423, /* 0x0.e33f6ffff */ + 0.890096127973, /* 0x0.e3dd56fff */ + 0.892507970338, /* 0x0.e47b67000 */ + 0.894928157336, /* 0x0.e51a03000 */ + 0.897355020043, /* 0x0.e5b90efff */ + 0.899788379682, /* 0x0.e65888000 */ + 0.902227103705, /* 0x0.e6f85afff */ + 0.904673457151, /* 0x0.e798ae000 */ + 0.907128036008, /* 0x0.e8398afff */ + 0.909585535528, /* 0x0.e8da99000 */ + 0.912051796915, /* 0x0.e97c3a000 */ + 0.914524436003, /* 0x0.ea1e46000 */ + 0.917003571999, /* 0x0.eac0bf000 */ + 0.919490039339, /* 0x0.eb63b2fff */ + 0.921983361257, /* 0x0.ec071a000 */ + 0.924488604054, /* 0x0.ecab48fff */ + 0.926989555360, /* 0x0.ed4f30000 */ + 0.929502844812, /* 0x0.edf3e6000 */ + 0.932021975503, /* 0x0.ee98fdfff */ + 0.934553921208, /* 0x0.ef3eecfff */ + 0.937083780759, /* 0x0.efe4b8fff */ + 0.939624726786, /* 0x0.f08b3f000 */ + 0.942198514924, /* 0x0.f133ebfff */ + 0.944726586343, /* 0x0.f1d99a000 */ + 0.947287976728, /* 0x0.f28176fff */ + 0.949856162070, /* 0x0.f329c5fff */ + 0.952431440345, /* 0x0.f3d28bfff */ + 0.955013573175, /* 0x0.f47bc5000 */ + 0.957603693021, /* 0x0.f52584000 */ + 0.960199773321, /* 0x0.f5cfa7000 */ + 0.962801992906, /* 0x0.f67a31000 */ + 0.965413510788, /* 0x0.f72556fff */ + 0.968030691152, /* 0x0.f7d0dc000 */ + 0.970655620084, /* 0x0.f87ce2fff */ + 0.973290979849, /* 0x0.f92998fff */ + 0.975926160805, /* 0x0.f9d64bfff */ + 0.978571653370, /* 0x0.fa83ac000 */ + 0.981225252139, /* 0x0.fb3193fff */ + 0.983885228626, /* 0x0.fbdfe6fff */ + 0.986552715296, /* 0x0.fc8eb7fff */ + 0.989228487027, /* 0x0.fd3e14000 */ + 0.991909801964, /* 0x0.fdedcd000 */ + 0.994601726545, /* 0x0.fe9e38000 */ + 0.997297704209, /* 0x0.ff4ee6fff */ + 1.000000000000, /* 0x1.000000000 */ + 1.002710938457, /* 0x1.00b1aa000 */ + 1.005429744692, /* 0x1.0163d7ffe */ + 1.008155703526, /* 0x1.02167dffe */ + 1.010888457284, /* 0x1.02c995fff */ + 1.013629436498, /* 0x1.037d38000 */ + 1.016377568250, /* 0x1.043152000 */ + 1.019134163841, /* 0x1.04e5f9ffe */ + 1.021896362316, /* 0x1.059b00000 */ + 1.024668931945, /* 0x1.0650b3ffe */ + 1.027446627635, /* 0x1.0706be001 */ + 1.030234098408, /* 0x1.07bd6bffe */ + 1.033023953416, /* 0x1.087441ffe */ + 1.035824656494, /* 0x1.092bce000 */ + 1.038632392900, /* 0x1.09e3d0001 */ + 1.041450142840, /* 0x1.0a9c79ffe */ + 1.044273972530, /* 0x1.0b558a001 */ + 1.047105550795, /* 0x1.0c0f1c001 */ + 1.049944162390, /* 0x1.0cc924001 */ + 1.052791833895, /* 0x1.0d83c4001 */ + 1.055645227426, /* 0x1.0e3ec3fff */ + 1.058507919326, /* 0x1.0efa60001 */ + 1.061377286898, /* 0x1.0fb66bfff */ + 1.064254641510, /* 0x1.1072fdffe */ + 1.067140102389, /* 0x1.113018000 */ + 1.070034146304, /* 0x1.11edc1fff */ + 1.072937250162, /* 0x1.12ac04001 */ + 1.075843691823, /* 0x1.136a7dfff */ + 1.078760385496, /* 0x1.1429a3ffe */ + 1.081685543070, /* 0x1.14e958000 */ + 1.084618330005, /* 0x1.15a98c000 */ + 1.087556362176, /* 0x1.166a18001 */ + 1.090508937863, /* 0x1.172b98001 */ + 1.093464612954, /* 0x1.17ed4bfff */ + 1.096430182434, /* 0x1.18afa5ffe */ + 1.099401354802, /* 0x1.19725e000 */ + 1.102381587017, /* 0x1.1a35adfff */ + 1.105370759965, /* 0x1.1af994000 */ + 1.108367800686, /* 0x1.1bbdfdffe */ + 1.111373305331, /* 0x1.1c82f6000 */ + 1.114387035385, /* 0x1.1d4878001 */ + 1.117408752440, /* 0x1.1e0e7ffff */ + 1.120437502874, /* 0x1.1ed4fe000 */ + 1.123474478729, /* 0x1.1f9c06000 */ + 1.126521706601, /* 0x1.2063ba001 */ + 1.129574775716, /* 0x1.212bd0001 */ + 1.132638812065, /* 0x1.21f49e000 */ + 1.135709524130, /* 0x1.22bddbffe */ + 1.138789534565, /* 0x1.2387b5fff */ + 1.141876101508, /* 0x1.2451fe000 */ + 1.144971728301, /* 0x1.251cddffe */ + 1.148077130296, /* 0x1.25e861ffe */ + 1.151189923305, /* 0x1.26b462001 */ + 1.154312610610, /* 0x1.278107ffe */ + 1.157440662410, /* 0x1.284e08001 */ + 1.160578370109, /* 0x1.291baa001 */ + 1.163725256932, /* 0x1.29e9e6000 */ + 1.166879892324, /* 0x1.2ab8a3ffe */ + 1.170044302935, /* 0x1.2b8805fff */ + 1.173205971694, /* 0x1.2c5739ffe */ + 1.176397800428, /* 0x1.2d2867ffe */ + 1.179586529747, /* 0x1.2df962001 */ + 1.182784795737, /* 0x1.2ecafbffe */ + 1.185991406414, /* 0x1.2f9d21ffe */ + 1.189206838636, /* 0x1.306fdc001 */ + 1.192430973067, /* 0x1.314328000 */ + 1.195664167430, /* 0x1.32170c001 */ + 1.198906540890, /* 0x1.32eb8a001 */ + 1.202157497408, /* 0x1.33c098000 */ + 1.205416083326, /* 0x1.349625fff */ + 1.208683252332, /* 0x1.356c43fff */ + 1.211961269402, /* 0x1.364318001 */ + 1.215246438983, /* 0x1.371a64000 */ + 1.218539118740, /* 0x1.37f22dffe */ + 1.221847295770, /* 0x1.38cafc000 */ + 1.225158572187, /* 0x1.39a3fdfff */ + 1.228481650325, /* 0x1.3a7dc5ffe */ + 1.231811761846, /* 0x1.3b5803fff */ + 1.235149741144, /* 0x1.3c32c5ffe */ + 1.238499879811, /* 0x1.3d0e53ffe */ + 1.241858124726, /* 0x1.3dea69fff */ + 1.245225191102, /* 0x1.3ec713fff */ + 1.248601436624, /* 0x1.3fa458000 */ + 1.251975655584, /* 0x1.40817a001 */ + 1.255380749731, /* 0x1.4160a2001 */ + 1.258783102010, /* 0x1.423f9bffe */ + 1.262198328973, /* 0x1.431f6e000 */ + 1.265619754780, /* 0x1.43ffa7fff */ + 1.269052743928, /* 0x1.44e0a4001 */ + 1.272490739830, /* 0x1.45c1f4000 */ + 1.275942921659, /* 0x1.46a432001 */ + 1.279397487615, /* 0x1.478697ffe */ + 1.282870173427, /* 0x1.486a2dffe */ + 1.286346316319, /* 0x1.494dfdffe */ + 1.289836049094, /* 0x1.4a32b2001 */ + 1.293333172770, /* 0x1.4b17e1ffe */ + 1.296839594835, /* 0x1.4bfdadfff */ + 1.300354957560, /* 0x1.4ce40fffe */ + 1.303882122055, /* 0x1.4dcb38001 */ + 1.307417988757, /* 0x1.4eb2f1ffe */ + 1.310960650439, /* 0x1.4f9b1dfff */ + 1.314516782746, /* 0x1.50842bfff */ + 1.318079948424, /* 0x1.516daffff */ + 1.321653246888, /* 0x1.5257de000 */ + 1.325237751030, /* 0x1.5342c8001 */ + 1.328829526907, /* 0x1.542e2c000 */ + 1.332433700535, /* 0x1.551a5fffe */ + 1.336045145966, /* 0x1.56070dffe */ + 1.339667558645, /* 0x1.56f473ffe */ + 1.343300342533, /* 0x1.57e287ffe */ + 1.346941947961, /* 0x1.58d130001 */ + 1.350594043714, /* 0x1.59c087ffe */ + 1.354256033883, /* 0x1.5ab085fff */ + 1.357932448365, /* 0x1.5ba175ffe */ + 1.361609339707, /* 0x1.5c926dfff */ + 1.365299344044, /* 0x1.5d8441ffe */ + 1.369003057507, /* 0x1.5e76fc001 */ + 1.372714757920, /* 0x1.5f6a3c000 */ + 1.376437187179, /* 0x1.605e2fffe */ + 1.380165219333, /* 0x1.615282001 */ + 1.383909463864, /* 0x1.6247e3ffe */ + 1.387661933907, /* 0x1.633dd0000 */ + 1.391424179060, /* 0x1.64345fffe */ + 1.395197510706, /* 0x1.652ba9fff */ + 1.399006724329, /* 0x1.66254dffe */ + 1.402773022651, /* 0x1.671c22000 */ + 1.406576037403, /* 0x1.68155dfff */ + 1.410389423392, /* 0x1.690f48001 */ +}; diff --git a/src/system/libroot/posix/glibc/arch/x86_64/Jamfile b/src/system/libroot/posix/glibc/arch/x86_64/Jamfile new file mode 100644 index 0000000000..8be5c91044 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/Jamfile @@ -0,0 +1,136 @@ +SubDir HAIKU_TOP src system libroot posix glibc arch x86_64 ; + +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch $(TARGET_ARCH) ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include arch generic ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc include ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc libio ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc stdlib ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc math ; +SubDirSysHdrs $(HAIKU_TOP) src system libroot posix glibc ; + +SubDirHdrs $(HAIKU_TOP) src system libroot posix glibc arch generic ; + +UsePrivateHeaders libroot ; + +if $(OPTIM) = -O0 { + OPTIM = -O ; +} + +# don't compile with debugging +DEBUG = 0 ; + +SubDirCcFlags -D_GNU_SOURCE -D_IEEE_LIBM -DPIC ; +SubDirAsFlags -DPIC ; + +local genericSources = + cmp.c dbl2mpn.c divrem.c + memrchr.c + mpn2dbl.c mpn2flt.c mpn2ldbl.c + mul.c mul_n.c + + branred.c doasin.c dosincos.c halfulp.c mpa.c mpatan.c mpatan2.c mpexp.c + mplog.c mpsqrt.c mptan.c sincos32.c slowexp.c slowpow.c + + e_acos.c e_acosf.c e_acosh.c e_acoshf.c e_acoshl.c e_asin.c e_asinf.c + e_asinl.c e_atan2.c e_atan2f.c e_atanh.c e_atanhf.c e_atanhl.c e_cosh.c + e_coshf.c e_coshl.c e_exp.c e_exp10.c e_exp10f.c e_exp10l.c e_exp2.c + e_exp2f.c e_expf.c e_fmod.c e_fmodf.c e_gamma_r.c e_gammaf_r.c e_gammal_r.c + e_hypot.c e_hypotf.c e_hypotl.c e_j0.c e_j0f.c e_j0l.c e_j1.c e_j1f.c + e_j1l.c e_jn.c e_jnf.c e_jnl.c e_lgamma_r.c e_lgammaf_r.c e_lgammal_r.c + e_log.c e_log10.c e_log10f.c e_log2.c e_log2f.c e_logf.c e_pow.c e_powf.c + e_rem_pio2.c e_rem_pio2f.c e_remainder.c e_remainderf.c e_scalb.c + e_scalbf.c e_sinh.c e_sinhf.c e_sinhl.c + + k_cos.c k_cosf.c k_rem_pio2.c k_rem_pio2f.c k_sin.c k_sinf.c k_tan.c + k_tanf.c + + s_asinh.c s_asinhf.c s_asinhl.c s_atan.c s_atanf.c s_cacos.c s_cacosf.c + s_cacosh.c s_cacoshf.c s_cacoshl.c s_cacosl.c s_casin.c s_casinf.c + s_casinh.c s_casinhf.c s_casinhl.c s_casinl.c s_catan.c s_catanf.c + s_catanh.c s_catanhf.c s_catanhl.c s_catanl.c s_cbrt.c s_cbrtf.c + s_cbrtl.c s_ccos.c s_ccosf.c s_ccosh.c s_ccoshf.c s_ccoshl.c s_ccosl.c + s_ceil.c s_ceilf.c s_cexp.c s_cexpf.c s_cexpl.c s_clog.c s_clog10.c + s_clog10f.c s_clog10l.c s_clogf.c s_clogl.c s_cos.c s_cosf.c s_cpow.c + s_cpowf.c s_cpowl.c s_cproj.c s_cprojf.c s_cprojl.c s_csin.c s_csinf.c + s_csinh.c s_csinhf.c s_csinhl.c s_csinl.c s_csqrt.c s_csqrtf.c s_csqrtl.c + s_ctan.c s_ctanf.c s_ctanh.c s_ctanhf.c s_ctanhl.c s_ctanl.c s_erf.c + s_erff.c s_erfl.c s_expm1.c s_expm1f.c s_fdim.c s_fdimf.c s_finite.c + s_finitef.c s_floor.c s_floorf.c s_fma.c s_fmaf.c s_fmal.c s_fpclassify.c + s_fpclassifyf.c s_frexp.c s_frexpf.c s_frexpl.c s_ilogb.c s_ilogbf.c + s_isinf.c s_isinff.c s_isnan.c s_isnanf.c s_ldexp.c s_ldexpf.c s_ldexpl.c + s_llround.c s_llroundf.c s_llroundl.c s_log1p.c s_log1pf.c s_logb.c + s_logbf.c s_lround.c s_lroundf.c s_lroundl.c s_matherr.c s_modf.c s_modff.c + s_modfl.c s_nan.c s_nanf.c s_nanl.c s_nearbyint.c s_nearbyintf.c + s_nextafter.c s_nextafterf.c s_nexttowardl.c s_remquo.c s_remquof.c + s_remquol.c s_rint.c s_rintf.c s_round.c s_roundf.c s_roundl.c s_scalbln.c + s_scalblnf.c s_scalblnl.c s_scalbn.c s_scalbnf.c s_signbit.c s_signbitf.c + s_signbitl.c s_signgam.c s_significand.c s_significandf.c s_sin.c + s_sincosf.c s_sinf.c s_tan.c s_tanf.c s_tanh.c s_tanhf.c s_tanhl.c + s_trunc.c s_truncf.c + + t_exp.c + + w_acos.c w_acosf.c w_acosh.c w_acoshf.c w_acoshl.c w_acosl.c w_asin.c + w_asinf.c w_asinl.c w_atan2.c w_atan2f.c w_atan2l.c w_atanh.c w_atanhf.c + w_atanhl.c w_cosh.c w_coshf.c w_coshl.c w_drem.c w_dremf.c w_dreml.c + w_exp.c w_exp10.c w_exp10f.c w_exp10l.c w_exp2.c w_exp2f.c w_exp2l.c + w_expf.c w_expl.c w_fmod.c w_fmodf.c w_fmodl.c w_hypot.c w_hypotf.c + w_hypotl.c w_j0.c w_j0f.c w_j0l.c w_j1.c w_j1f.c w_j1l.c w_jn.c w_jnf.c + w_jnl.c w_lgamma.c w_lgamma_r.c w_lgammaf.c w_lgammaf_r.c w_lgammal.c + w_lgammal_r.c w_log.c w_log10.c w_log10f.c w_log10l.c w_log2.c w_log2f.c + w_log2l.c w_logf.c w_logl.c w_pow.c w_powf.c w_powl.c w_remainder.c + w_remainderf.c w_remainderl.c w_scalb.c w_scalbf.c w_scalbl.c w_sinh.c + w_sinhf.c w_sinhl.c w_sqrt.c w_sqrtf.c w_sqrtl.c w_tgamma.c w_tgammaf.c + w_tgammal.c +; + + +MergeObject posix_gnu_arch_$(TARGET_ARCH)_e.o : + e_acosl.c e_atan2l.c e_exp2l.S e_expl.c e_fmodl.S e_log10l.S e_log2l.S + e_logl.S e_powl.S e_remainderl.S e_rem_pio2l.c e_scalbl.S e_sqrt.c + e_sqrtf.c e_sqrtl.c +; + + +MergeObject posix_gnu_arch_$(TARGET_ARCH)_k.o : + k_cosl.c k_rem_pio2l.c k_sinl.c k_tanl.c +; + +MergeObject posix_gnu_arch_$(TARGET_ARCH)_s.o : + s_atanl.c s_ceill.S s_copysignf.S s_copysignl.S s_copysign.S s_cosl.S + s_expm1l.S s_fabs.c s_fabsf.c s_fabsl.S s_fdiml.S s_finitel.S s_floorl.S + s_fmaxf.S s_fmaxl.S s_fmax.S s_fminf.S s_fminl.S s_fmin.S s_fpclassifyl.c + s_ilogbl.S s_isinfl.c s_isnanl.c s_llrintf.S s_llrintl.S s_llrint.S + s_log1pl.S s_logbl.c s_lrintf.S s_lrintl.S s_lrint.S s_nearbyintl.S + s_nextafterl.c s_nexttoward.c s_nexttowardf.c s_rintl.c s_scalbnl.S + s_significandl.c s_sincosl.S s_sincos.S s_sinl.S s_tanl.S s_truncl.S +; + +MergeObject posix_gnu_arch_$(TARGET_ARCH)_other.o : + add_n.S + addmul_1.S + fegetround.c + fesetenv.c + fesetround.c + ldbl2mpn.c + + mul_1.S + lshift.S rshift.S + sub_n.S + submul_1.S +; + +MergeObject posix_gnu_arch_$(TARGET_ARCH)_generic.o : + $(genericSources) +; + +MergeObjectFromObjects posix_gnu_arch_$(TARGET_ARCH).o : : + posix_gnu_arch_$(TARGET_ARCH)_e.o + posix_gnu_arch_$(TARGET_ARCH)_k.o + posix_gnu_arch_$(TARGET_ARCH)_s.o + posix_gnu_arch_$(TARGET_ARCH)_other.o + posix_gnu_arch_$(TARGET_ARCH)_generic.o +; + +SEARCH on [ FGristFiles $(genericSources) ] + = [ FDirName $(HAIKU_TOP) src system libroot posix glibc arch generic ] ; diff --git a/src/system/libroot/posix/glibc/arch/x86_64/add_n.S b/src/system/libroot/posix/glibc/arch/x86_64/add_n.S new file mode 100644 index 0000000000..7883f6c840 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/add_n.S @@ -0,0 +1,42 @@ +/* Add two limb vectors of the same length > 0 and store sum in a third + limb vector. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY (__mpn_add_n) + leaq (%rsi,%rcx,8), %rsi + leaq (%rdi,%rcx,8), %rdi + leaq (%rdx,%rcx,8), %rdx + negq %rcx + xorl %eax, %eax # clear cy + .p2align 2 +L(loop): + movq (%rsi,%rcx,8), %rax + movq (%rdx,%rcx,8), %r10 + adcq %r10, %rax + movq %rax, (%rdi,%rcx,8) + incq %rcx + jne L(loop) + movq %rcx, %rax # zero %rax + adcq %rax, %rax + ret +END (__mpn_add_n) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/addmul_1.S b/src/system/libroot/posix/glibc/arch/x86_64/addmul_1.S new file mode 100644 index 0000000000..bdb5226a33 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/addmul_1.S @@ -0,0 +1,46 @@ +/* AMD64 __mpn_addmul_1 -- Multiply a limb vector with a limb and add + the result to a second limb vector. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY (__mpn_addmul_1) + movq %rdx, %r11 + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %r11 + xorl %r8d, %r8d + xorl %r10d, %r10d + .p2align 2 +L(loop): + movq (%rsi,%r11,8), %rax + mulq %rcx + addq (%rdi,%r11,8), %rax + adcq %r10, %rdx + addq %r8, %rax + movq %r10, %r8 + movq %rax, (%rdi,%r11,8) + adcq %rdx, %r8 + incq %r11 + jne L(loop) + movq %r8, %rax + ret +END (__mpn_addmul_1) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_acosl.c b/src/system/libroot/posix/glibc/arch/x86_64/e_acosl.c new file mode 100644 index 0000000000..61db1481bb --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_acosl.c @@ -0,0 +1,25 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include "math_private.h" + +long double +__ieee754_acosl (long double x) +{ + long double res; + + /* acosl = atanl (sqrtl(1 - x^2) / x) */ + asm ( "fld %%st\n" + "fmul %%st(0)\n" /* x^2 */ + "fld1\n" + "fsubp\n" /* 1 - x^2 */ + "fsqrt\n" /* sqrtl (1 - x^2) */ + "fxch %%st(1)\n" + "fpatan" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_atan2l.c b/src/system/libroot/posix/glibc/arch/x86_64/e_atan2l.c new file mode 100644 index 0000000000..c3b1795f9a --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_atan2l.c @@ -0,0 +1,18 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include "math_private.h" + +long double +__ieee754_atan2l (long double y, long double x) +{ + long double res; + + asm ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_exp2l.S b/src/system/libroot/posix/glibc/arch/x86_64/e_exp2l.S new file mode 100644 index 0000000000..336b989098 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_exp2l.S @@ -0,0 +1,38 @@ +/* + * Written by J.T. Conklin . + * Adapted for exp2 by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + * Public domain. + */ + +#include + +ENTRY(__ieee754_exp2l) + fldt 8(%rsp) +/* I added the following ugly construct because exp(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + frndint /* int(x) */ + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: ret +END (__ieee754_exp2l) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_expl.c b/src/system/libroot/posix/glibc/arch/x86_64/e_expl.c new file mode 100644 index 0000000000..1b299239e7 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_expl.c @@ -0,0 +1,77 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +/* + * The 8087 method for the exponential function is to calculate + * exp(x) = 2^(x log2(e)) + * after separating integer and fractional parts + * x log2(e) = i + f, |f| <= .5 + * 2^i is immediate but f needs to be precise for long double accuracy. + * Suppress range reduction error in computing f by the following. + * Separate x into integer and fractional parts + * x = xi + xf, |xf| <= .5 + * Separate log2(e) into the sum of an exact number c0 and small part c1. + * c0 + c1 = log2(e) to extra precision + * Then + * f = (c0 xi - i) + c0 xf + c1 x + * where c0 xi is exact and so also is (c0 xi - i). + * -- moshier@na-net.ornl.gov + */ + +#include "math_private.h" + +static const long double c0 = 1.44268798828125L; +static const long double c1 = 7.05260771340735992468e-6L; + +long double +__ieee754_expl (long double x) +{ + long double res; + +/* I added the following ugly construct because expl(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + asm ("fxam\n\t" /* Is NaN or +-Inf? */ + "fstsw %%ax\n\t" + "movb $0x45, %%dh\n\t" + "andb %%ah, %%dh\n\t" + "cmpb $0x05, %%dh\n\t" + "je 1f\n\t" /* Is +-Inf, jump. */ + "fldl2e\n\t" /* 1 log2(e) */ + "fmul %%st(1),%%st\n\t" /* 1 x log2(e) */ + "frndint\n\t" /* 1 i */ + "fld %%st(1)\n\t" /* 2 x */ + "frndint\n\t" /* 2 xi */ + "fld %%st(1)\n\t" /* 3 i */ + "fldt %2\n\t" /* 4 c0 */ + "fld %%st(2)\n\t" /* 5 xi */ + "fmul %%st(1),%%st\n\t" /* 5 c0 xi */ + "fsubp %%st,%%st(2)\n\t" /* 4 f = c0 xi - i */ + "fld %%st(4)\n\t" /* 5 x */ + "fsub %%st(3),%%st\n\t" /* 5 xf = x - xi */ + "fmulp %%st,%%st(1)\n\t" /* 4 c0 xf */ + "faddp %%st,%%st(1)\n\t" /* 3 f = f + c0 xf */ + "fldt %3\n\t" /* 4 */ + "fmul %%st(4),%%st\n\t" /* 4 c1 * x */ + "faddp %%st,%%st(1)\n\t" /* 3 f = f + c1 * x */ + "f2xm1\n\t" /* 3 2^(fract(x * log2(e))) - 1 */ + "fld1\n\t" /* 4 1.0 */ + "faddp\n\t" /* 3 2^(fract(x * log2(e))) */ + "fstp %%st(1)\n\t" /* 2 */ + "fscale\n\t" /* 2 scale factor is st(1); e^x */ + "fstp %%st(1)\n\t" /* 1 */ + "fstp %%st(1)\n\t" /* 0 */ + "jmp 2f\n\t" + "1:\ttestl $0x200, %%eax\n\t" /* Test sign. */ + "jz 2f\n\t" /* If positive, jump. */ + "fstp %%st\n\t" + "fldz\n\t" /* Set result to 0. */ + "2:\t\n" + : "=t" (res) : "0" (x), "m" (c0), "m" (c1) : "ax", "dx"); + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_fmodl.S b/src/system/libroot/posix/glibc/arch/x86_64/e_fmodl.S new file mode 100644 index 0000000000..2967bf224b --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_fmodl.S @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +RCSID("$NetBSD: $") + +ENTRY(__ieee754_fmodl) + fldt 24(%rsp) + fldt 8(%rsp) +1: fprem + fstsw %ax + and $04,%ah + jnz 1b + fstp %st(1) + ret +END (__ieee754_fmodl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_log10l.S b/src/system/libroot/posix/glibc/arch/x86_64/e_log10l.S new file mode 100644 index 0000000000..633234b744 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_log10l.S @@ -0,0 +1,67 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * + * Changed to use fyl2xp1 for values near 1, . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +RCSID("$NetBSD: $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_log10l) + fldlg2 // log10(2) + fldt 8(%rsp) // x : log10(2) + fxam + fnstsw + fld %st // x : x : log10(2) + testb $1, %ah + jnz 3f // in case x is NaN or ±Inf +4: fsubl MO(one) // x-1 : x : log10(2) + fld %st // x-1 : x-1 : x : log10(2) + fabs // |x-1| : x-1 : x : log10(2) + fcompl MO(limit) // x-1 : x : log10(2) + fnstsw // x-1 : x : log10(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log10(2) + fyl2xp1 // log10(x) + ret + +2: fstp %st(0) // x : log10(2) + fyl2x // log10(x) + ret + +3: testb $4, %ah + jnz 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +END(__ieee754_log10l) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_log2l.S b/src/system/libroot/posix/glibc/arch/x86_64/e_log2l.S new file mode 100644 index 0000000000..f04d30a05a --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_log2l.S @@ -0,0 +1,64 @@ +/* + * Written by J.T. Conklin . + * Adapted for use as log2 by Ulrich Drepper . + * Public domain. + * + * Changed to use fyl2xp1 for values near 1, . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_log2l) + fldl MO(one) + fldt 8(%rsp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + testb $1, %ah + jnz 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl MO(limit) // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + ret + +3: testb $4, %ah + jnz 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +END (__ieee754_log2l) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_logl.S b/src/system/libroot/posix/glibc/arch/x86_64/e_logl.S new file mode 100644 index 0000000000..2ba91eedfd --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_logl.S @@ -0,0 +1,66 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +RCSID("$NetBSD: $") + + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_logl) + fldln2 // log(2) + fldt 8(%rsp) // x : log(2) + fxam + fnstsw + fld %st // x : x : log(2) + testb $1, %ah + jnz 3f // in case x is NaN or +-Inf +4: fsubl MO(one) // x-1 : x : log(2) + fld %st // x-1 : x-1 : x : log(2) + fabs // |x-1| : x-1 : x : log(2) + fcompl MO(limit) // x-1 : x : log(2) + fnstsw // x-1 : x : log(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log(2) + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : log(2) + fyl2x // log(x) + ret + +3: testb $4, %ah + jnz 4b // in case x is +-Inf + fstp %st(1) + fstp %st(1) + ret +END (__ieee754_logl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_powl.S b/src/system/libroot/posix/glibc/arch/x86_64/e_powl.S new file mode 100644 index 0000000000..4959bea7ac --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_powl.S @@ -0,0 +1,341 @@ +/* ix87 specific implementation of pow function. + Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(infinity,@object) +inf_zero: +infinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f + ASM_SIZE_DIRECTIVE(infinity) + ASM_TYPE_DIRECTIVE(zero,@object) +zero: .double 0.0 + ASM_SIZE_DIRECTIVE(zero) + ASM_TYPE_DIRECTIVE(minf_mzero,@object) +minf_mzero: +minfinity: + .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff +mzero: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + ASM_SIZE_DIRECTIVE(minf_mzero) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + ASM_TYPE_DIRECTIVE(limit,@object) +limit: .double 0.29 + ASM_SIZE_DIRECTIVE(limit) + ASM_TYPE_DIRECTIVE(p63,@object) +p63: + .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43 + ASM_SIZE_DIRECTIVE(p63) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_powl) + fldt 24(%rsp) // y + fxam + + + fnstsw + movb %ah, %dl + andb $0x45, %ah + cmpb $0x40, %ah // is y == 0 ? + je 11f + + cmpb $0x05, %ah // is y == ±inf ? + je 12f + + cmpb $0x01, %ah // is y == NaN ? + je 30f + + fldt 8(%rsp) // x : y + + fxam + fnstsw + movb %ah, %dh + andb $0x45, %ah + cmpb $0x40, %ah + je 20f // x is ±0 + + cmpb $0x05, %ah + je 15f // x is ±inf + + fxch // y : x + + /* fistpll raises invalid exception for |y| >= 1L<<63. */ + fldl MO(p63) // 1L<<63 : y : x + fld %st(1) // y : 1L<<63 : y : x + fabs // |y| : 1L<<63 : y : x + fcomip %st(1), %st // 1L<<63 : y : x + fstp %st(0) // y : x + jnc 2f + + /* First see whether `y' is a natural number. In this case we + can use a more precise algorithm. */ + fld %st // y : y : x + fistpll -8(%rsp) // y : x + fildll -8(%rsp) // int(y) : y : x + fucomip %st(1),%st // y : x + jne 2f + + /* OK, we have an integer value for y. */ + mov -8(%rsp),%eax + mov -4(%rsp),%edx + orl $0, %edx + fstp %st(0) // x + jns 4f // y >= 0, jump + fdivrl MO(one) // 1/x (now referred to as x) + negl %eax + adcl $0, %edx + negl %edx +4: fldl MO(one) // 1 : x + fxch + +6: shrdl $1, %edx, %eax + jnc 5f + fxch + fmul %st(1) // x : ST*x + fxch +5: fmul %st(0), %st // x*x : ST*x + shrl $1, %edx + movl %eax, %ecx + orl %edx, %ecx + jnz 6b + fstp %st(0) // ST*x + ret + + /* y is ±NAN */ +30: fldt 8(%rsp) // x : y + fldl MO(one) // 1.0 : x : y + fucomip %st(1),%st // x : y + je 31f + fxch // y : x +31: fstp %st(1) + ret + + .align ALIGNARG(4) +2: /* y is a real number. */ + fxch // x : y + fldl MO(one) // 1.0 : x : y + fldl MO(limit) // 0.29 : 1.0 : x : y + fld %st(2) // x : 0.29 : 1.0 : x : y + fsub %st(2) // x-1 : 0.29 : 1.0 : x : y + fabs // |x-1| : 0.29 : 1.0 : x : y + fucompp // 1.0 : x : y + fnstsw + fxch // x : 1.0 : y + test $4500,%eax + jz 7f + fsub %st(1) // x-1 : 1.0 : y + fyl2xp1 // log2(x) : y + jmp 8f + +7: fyl2x // log2(x) : y +8: fmul %st(1) // y*log2(x) : y + fxam + fnstsw + andb $0x45, %ah + cmpb $0x05, %ah // is y*log2(x) == ±inf ? + je 28f + fst %st(1) // y*log2(x) : y*log2(x) + frndint // int(y*log2(x)) : y*log2(x) + fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x)) + fxch // fract(y*log2(x)) : int(y*log2(x)) + f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x)) + faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x)) + fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x)) + fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x)) + ret + +28: fstp %st(1) // y*log2(x) + fldl MO(one) // 1 : y*log2(x) + fscale // 2^(y*log2(x)) : y*log2(x) + fstp %st(1) // 2^(y*log2(x)) + ret + + // pow(x,±0) = 1 + .align ALIGNARG(4) +11: fstp %st(0) // pop y + fldl MO(one) + ret + + // y == ±inf + .align ALIGNARG(4) +12: fstp %st(0) // pop y + fldl MO(one) // 1 + fldt 8(%rsp) // x : 1 + fabs // abs(x) : 1 + fucompp // < 1, == 1, or > 1 + fnstsw + andb $0x45, %ah + cmpb $0x45, %ah + je 13f // jump if x is NaN + + cmpb $0x40, %ah + je 14f // jump if |x| == 1 + + shlb $1, %ah + xorb %ah, %dl + andl $2, %edx +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rdx, 4) +#else + fldl inf_zero(,%rdx, 4) +#endif + ret + + .align ALIGNARG(4) +14: fldl MO(one) + ret + + .align ALIGNARG(4) +13: fldt 8(%rsp) // load x == NaN + ret + + .align ALIGNARG(4) + // x is ±inf +15: fstp %st(0) // y + testb $2, %dh + jz 16f // jump if x == +inf + + // We must find out whether y is an odd integer. + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // + jne 17f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp), %eax + mov -4(%rsp), %edx + andb $1, %al + jz 18f // jump if not odd + // It's an odd integer. + shrl $31, %edx +#ifdef PIC + lea minf_mzero(%rip),%rcx + fldl (%rcx, %rdx, 8) +#else + fldl minf_mzero(,%rdx, 8) +#endif + ret + + .align ALIGNARG(4) +16: fcompl MO(zero) + fnstsw + shrl $5, %eax + andl $8, %eax +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rax, 1) +#else + fldl inf_zero(,%rax, 1) +#endif + ret + + .align ALIGNARG(4) +17: shll $30, %edx // sign bit for y in right position +18: shrl $31, %edx +#ifdef PIC + lea inf_zero(%rip),%rcx + fldl (%rcx, %rdx, 8) +#else + fldl inf_zero(,%rdx, 8) +#endif + ret + + .align ALIGNARG(4) + // x is ±0 +20: fstp %st(0) // y + testb $2, %dl + jz 21f // y > 0 + + // x is ±0 and y is < 0. We must find out whether y is an odd integer. + testb $2, %dh + jz 25f + + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // + jne 26f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp),%eax + mov -4(%rsp),%edx + andb $1, %al + jz 27f // jump if not odd + // It's an odd integer. + // Raise divide-by-zero exception and get minus infinity value. + fldl MO(one) + fdivl MO(zero) + fchs + ret + +25: fstp %st(0) +26: +27: // Raise divide-by-zero exception and get infinity value. + fldl MO(one) + fdivl MO(zero) + ret + + .align ALIGNARG(4) + // x is ±0 and y is > 0. We must find out whether y is an odd integer. +21: testb $2, %dh + jz 22f + + fld %st // y : y + fistpll -8(%rsp) // y + fildll -8(%rsp) // int(y) : y + fucomip %st(1),%st + ffreep %st // + jne 23f + + // OK, the value is an integer, but is it odd? + mov -8(%rsp),%eax + mov -4(%rsp),%edx + andb $1, %al + jz 24f // jump if not odd + // It's an odd integer. + fldl MO(mzero) + ret + +22: fstp %st(0) +23: +24: fldl MO(zero) + ret + +END(__ieee754_powl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_rem_pio2l.c b/src/system/libroot/posix/glibc/arch/x86_64/e_rem_pio2l.c new file mode 100644 index 0000000000..1347b0468c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_rem_pio2l.c @@ -0,0 +1,3 @@ +/* Empty. This file is only meant to avoid compiling the file with the + same name in the libm-ieee754 directory. The code is not used since + there is an assembler version for all users of this file. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_remainderl.S b/src/system/libroot/posix/glibc/arch/x86_64/e_remainderl.S new file mode 100644 index 0000000000..480b1cad8b --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_remainderl.S @@ -0,0 +1,20 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +ENTRY(__ieee754_remainderl) + fldt 24(%rsp) + fldt 8(%rsp) +1: fprem1 + fstsw %ax + testl $0x400,%eax + jnz 1b + fstp %st(1) + ret +END (__ieee754_remainderl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_scalbl.S b/src/system/libroot/posix/glibc/arch/x86_64/e_scalbl.S new file mode 100644 index 0000000000..6b229705ba --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_scalbl.S @@ -0,0 +1,100 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger + * + * Correct handling of y==-inf + */ + +#include + +RCSID("$NetBSD: $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(zero_nan,@object) +zero_nan: + .double 0.0 +nan: .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f +minus_zero: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + .byte 0, 0, 0, 0, 0, 0, 0xff, 0x7f + ASM_SIZE_DIRECTIVE(zero_nan) + + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__ieee754_scalbl) + fldt 24(%rsp) + fxam + fnstsw + fldt 8(%rsp) + andl $0x4700, %eax + cmpl $0x0700, %eax + je 1f + andl $0x4500, %eax + cmpl $0x0100, %eax + je 2f + fxam + fnstsw + andl $0x4500, %eax + cmpl $0x0100, %eax + je 3f + fld %st(1) + frndint + fcomip %st(2), %st + jne 4f + fscale + fstp %st(1) + ret + + /* y is -inf */ +1: fxam + fnstsw + movl 16(%rsp), %edx + shrl $5, %eax + fstp %st + fstp %st + andl $0x8000, %edx + andl $8, %eax + jnz 4f + shrl $11, %edx + addl %edx, %eax +#ifdef PIC + lea zero_nan(%rip),%rdx + fldl (%rdx,%rax,1) +#else + fldl zero_nan(%rax, 1) +#endif + ret + + /* The result is NaN, but we must not raise an exception. + So use a variable. */ +2: fstp %st + fstp %st + fldl MO(nan) + ret + + /* The first parameter is a NaN. Return it. */ +3: fstp %st(1) + ret + + /* Return NaN and raise the invalid exception. */ +4: fstp %st + fstp %st + fldz + fdiv %st + ret +END(__ieee754_scalbl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_sqrt.c b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrt.c new file mode 100644 index 0000000000..0791c453a7 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrt.c @@ -0,0 +1,30 @@ +/* Square root of floating point number. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "math_private.h" + +double +__ieee754_sqrt (double x) +{ + double res; + + asm ("sqrtsd %0, %1" : "=x" (res) : "x" (x)); + + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtf.c b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtf.c new file mode 100644 index 0000000000..922e03f318 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtf.c @@ -0,0 +1,30 @@ +/* Square root of floating point number. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "math_private.h" + +float +__ieee754_sqrtf (float x) +{ + float res; + + asm ("sqrtss %0, %1" : "=x" (res) : "x" (x)); + + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtl.c b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtl.c new file mode 100644 index 0000000000..34cc6eafee --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/e_sqrtl.c @@ -0,0 +1,18 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include "math_private.h" + +long double +__ieee754_sqrtl (long double x) +{ + long double res; + + asm ("fsqrt" : "=t" (res) : "0" (x)); + + return res; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/fegetround.c b/src/system/libroot/posix/glibc/arch/x86_64/fegetround.c new file mode 100644 index 0000000000..f237b18d1d --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/fegetround.c @@ -0,0 +1,33 @@ +/* Return current rounding direction. + Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetround (void) +{ + int cw; + /* We only check the x87 FPU unit. The SSE unit should be the same + - and if it's not the same there's no way to signal it. */ + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} diff --git a/src/system/libroot/posix/glibc/arch/x86_64/fesetenv.c b/src/system/libroot/posix/glibc/arch/x86_64/fesetenv.c new file mode 100644 index 0000000000..8a3b7a0744 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/fesetenv.c @@ -0,0 +1,89 @@ +/* Install given floating-point environment. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ + __asm__ ("fnstenv %0\n" + "stmxcsr %1" : "=m" (*&temp), "=m" (*&temp.__mxcsr)); + + if (envp == FE_DFL_ENV) + { + temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word &= ~FE_TOWARDZERO; + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + /* Set mask for SSE MXCSR. */ + temp.__mxcsr |= (FE_ALL_EXCEPT << 7); + /* Set rounding to FE_TONEAREST. */ + temp.__mxcsr &= ~ 0x6000; + temp.__mxcsr |= (FE_TONEAREST << 3); + } + else if (envp == FE_NOMASK_ENV) + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + /* Set mask for SSE MXCSR. */ + /* Set rounding to FE_TONEAREST. */ + temp.__mxcsr &= ~ 0x6000; + temp.__mxcsr |= (FE_TONEAREST << 3); + /* Do not mask exceptions. */ + temp.__mxcsr &= ~(FE_ALL_EXCEPT << 7); + } + else + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word |= (envp->__control_word + & (FE_ALL_EXCEPT | FE_TOWARDZERO)); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + temp.__eip = envp->__eip; + temp.__cs_selector = envp->__cs_selector; + temp.__opcode = envp->__opcode; + temp.__data_offset = envp->__data_offset; + temp.__data_selector = envp->__data_selector; + temp.__mxcsr = envp->__mxcsr; + } + + __asm__ ("fldenv %0\n" + "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr)); + + /* Success. */ + return 0; +} +libm_hidden_def (fesetenv) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/fesetround.c b/src/system/libroot/posix/glibc/arch/x86_64/fesetround.c new file mode 100644 index 0000000000..408116eee8 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/fesetround.c @@ -0,0 +1,47 @@ +/* Set current rounding direction. + Copyright (C) 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fesetround (int round) +{ + unsigned short int cw; + int mxcsr; + + if ((round & ~0xc00) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + /* First set the x87 FPU. */ + asm ("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + asm ("fldcw %0" : : "m" (*&cw)); + + /* And now the MSCSR register for SSE, the precision is at different bit + positions in the different units, we need to shift it 3 bits. */ + asm ("stmxcsr %0" : "=m" (*&mxcsr)); + mxcsr &= ~ 0x6000; + mxcsr |= round << 3; + asm ("ldmxcsr %0" : : "m" (*&mxcsr)); + + return 0; +} +libm_hidden_def (fesetround) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/k_cosl.c b/src/system/libroot/posix/glibc/arch/x86_64/k_cosl.c new file mode 100644 index 0000000000..eea55a98d2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/k_cosl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/k_rem_pio2l.c b/src/system/libroot/posix/glibc/arch/x86_64/k_rem_pio2l.c new file mode 100644 index 0000000000..eea55a98d2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/k_rem_pio2l.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/k_sinl.c b/src/system/libroot/posix/glibc/arch/x86_64/k_sinl.c new file mode 100644 index 0000000000..eea55a98d2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/k_sinl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/k_tanl.c b/src/system/libroot/posix/glibc/arch/x86_64/k_tanl.c new file mode 100644 index 0000000000..eea55a98d2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/k_tanl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/ldbl2mpn.c b/src/system/libroot/posix/glibc/arch/x86_64/ldbl2mpn.c new file mode 100644 index 0000000000..66ac0a47a4 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/ldbl2mpn.c @@ -0,0 +1 @@ +#include "../x86/ldbl2mpn.c" diff --git a/src/system/libroot/posix/glibc/arch/x86_64/lshift.S b/src/system/libroot/posix/glibc/arch/x86_64/lshift.S new file mode 100644 index 0000000000..5ac66f0a36 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/lshift.S @@ -0,0 +1,60 @@ +/* AMD64 __mpn_lshift -- + Copyright 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + + .text +ENTRY (__mpn_lshift) + movq -8(%rsi,%rdx,8), %mm7 + movd %ecx, %mm1 + movl $64, %eax + subl %ecx, %eax + movd %eax, %mm0 + movq %mm7, %mm3 + psrlq %mm0, %mm7 + movd %mm7, %rax + subq $2, %rdx + jl L(endo) + .p2align 2 +L(loop): + movq (%rsi,%rdx,8), %mm6 + movq %mm6, %mm2 + psrlq %mm0, %mm6 + psllq %mm1, %mm3 + por %mm6, %mm3 + movq %mm3, 8(%rdi,%rdx,8) + je L(ende) + movq -8(%rsi,%rdx,8), %mm7 + movq %mm7, %mm3 + psrlq %mm0, %mm7 + psllq %mm1, %mm2 + por %mm7, %mm2 + movq %mm2, (%rdi,%rdx,8) + subq $2, %rdx + jge L(loop) +L(endo): + movq %mm3, %mm2 +L(ende): + psllq %mm1, %mm2 + movq %mm2, (%rdi) + emms + ret +END (__mpn_lshift) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/math_private.h b/src/system/libroot/posix/glibc/arch/x86_64/math_private.h new file mode 100644 index 0000000000..4febcbb5ec --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/math_private.h @@ -0,0 +1,21 @@ +#ifndef _MATH_PRIVATE_H + +#define math_opt_barrier(x) \ +({ __typeof(x) __x; \ + if (sizeof (x) <= sizeof (double)) \ + __asm ("" : "=x" (__x) : "0" (x)); \ + else \ + __asm ("" : "=t" (__x) : "0" (x)); \ + __x; }) +#define math_force_eval(x) \ +do \ + { \ + if (sizeof (x) <= sizeof (double)) \ + __asm __volatile ("" : : "x" (x)); \ + else \ + __asm __volatile ("" : : "f" (x)); \ + } \ +while (0) + +#include +#endif diff --git a/src/system/libroot/posix/glibc/arch/x86_64/mul_1.S b/src/system/libroot/posix/glibc/arch/x86_64/mul_1.S new file mode 100644 index 0000000000..978916b72c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/mul_1.S @@ -0,0 +1,42 @@ +/* AMD64 __mpn_mul_1 -- Multiply a limb vector with a limb and store + the result in a second limb vector. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include +#include "asm-syntax.h" + + .text +ENTRY (__mpn_mul_1) + movq %rdx, %r11 + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %r11 + xorl %r8d, %r8d +L(loop): + movq (%rsi,%r11,8), %rax + mulq %rcx + addq %r8, %rax + movl $0, %r8d + adcq %rdx, %r8 + movq %rax, (%rdi,%r11,8) + incq %r11 + jne L(loop) + movq %r8, %rax + ret +END (__mpn_mul_1) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/rshift.S b/src/system/libroot/posix/glibc/arch/x86_64/rshift.S new file mode 100644 index 0000000000..ee0c8aa15c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/rshift.S @@ -0,0 +1,62 @@ +/* AMD64 __mpn_rshift -- + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY (__mpn_rshift) + movq (%rsi), %mm7 + movd %ecx, %mm1 + movl $64, %eax + subl %ecx, %eax + movd %eax, %mm0 + movq %mm7, %mm3 + psllq %mm0, %mm7 + movd %mm7, %rax + leaq (%rsi,%rdx,8), %rsi + leaq (%rdi,%rdx,8), %rdi + negq %rdx + addq $2, %rdx + jg L(endo) + .p2align 2 +L(loop): + movq -8(%rsi,%rdx,8), %mm6 + movq %mm6, %mm2 + psllq %mm0, %mm6 + psrlq %mm1, %mm3 + por %mm6, %mm3 + movq %mm3, -16(%rdi,%rdx,8) + je L(ende) + movq (%rsi,%rdx,8), %mm7 + movq %mm7, %mm3 + psllq %mm0, %mm7 + psrlq %mm1, %mm2 + por %mm7, %mm2 + movq %mm2, -8(%rdi,%rdx,8) + addq $2, %rdx + jle L(loop) +L(endo): + movq %mm3, %mm2 +L(ende): + psrlq %mm1, %mm2 + movq %mm2, -8(%rdi) + emms + ret +END (__mpn_rshift) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_atanl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_atanl.c new file mode 100644 index 0000000000..fff764817b --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_atanl.c @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + */ + +#include "math_private.h" + +long double +__atanl (long double x) +{ + long double res; + + asm ("fld1\n" + "fpatan" + : "=t" (res) : "0" (x)); + + return res; +} + +weak_alias (__atanl, atanl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_ceill.S b/src/system/libroot/posix/glibc/arch/x86_64/s_ceill.S new file mode 100644 index 0000000000..efc8dd995e --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_ceill.S @@ -0,0 +1,31 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Changes for x86-64 by Andreas Jaeger + * Public domain. + */ + +#include + + +ENTRY(__ceill) + fldt 8(%rsp) + + fstcw -4(%rsp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x0800,%edx /* round towards +oo */ + orl -4(%rsp),%edx + andl $0xfbff,%edx + movl %edx,-8(%rsp) + fldcw -8(%rsp) /* load modified control word */ + + frndint /* round */ + + fldcw -4(%rsp) /* restore original control word */ + + ret +END (__ceill) +weak_alias (__ceill, ceill) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_copysign.S b/src/system/libroot/posix/glibc/arch/x86_64/s_copysign.S new file mode 100644 index 0000000000..f3d9b0cbb4 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_copysign.S @@ -0,0 +1,55 @@ +/* copy sign, double version. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(signmask,@object) +signmask: + .byte 0, 0, 0, 0, 0, 0, 0, 0x80 + .byte 0, 0, 0, 0, 0, 0, 0, 0 + ASM_SIZE_DIRECTIVE(signmask) + ASM_TYPE_DIRECTIVE(othermask,@object) +othermask: + .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f + .byte 0, 0, 0, 0, 0, 0, 0, 0 + ASM_SIZE_DIRECTIVE(othermask) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__copysign) + andpd MO(othermask),%xmm0 + andpd MO(signmask),%xmm1 + orpd %xmm1,%xmm0 + ret +END (__copysign) + +weak_alias (__copysign, copysign) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_copysignf.S b/src/system/libroot/posix/glibc/arch/x86_64/s_copysignf.S new file mode 100644 index 0000000000..0fbe1d4c96 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_copysignf.S @@ -0,0 +1,50 @@ +/* copy sign, double version. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(mask,@object) +mask: + .byte 0xff, 0xff, 0xff, 0x7f + ASM_SIZE_DIRECTIVE(mask) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__copysignf) + movss MO(mask),%xmm3 + andps %xmm3,%xmm0 + andnps %xmm1,%xmm3 + orps %xmm3,%xmm0 + retq +END (__copysignf) + +weak_alias (__copysignf, copysignf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_copysignl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_copysignl.S new file mode 100644 index 0000000000..2ffd612d65 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_copysignl.S @@ -0,0 +1,22 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper . + * Adopted for x86-64 by Andreas Jaeger . + * Public domain. + */ + +#include + +RCSID("$NetBSD: $") + +ENTRY(__copysignl) + movl 32(%rsp),%edx + movl 16(%rsp),%eax + andl $0x8000,%edx + andl $0x7fff,%eax + orl %edx,%eax + movl %eax,16(%rsp) + fldt 8(%rsp) + ret +END (__copysignl) +weak_alias (__copysignl, copysignl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_cosl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_cosl.S new file mode 100644 index 0000000000..e9f669369c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_cosl.S @@ -0,0 +1,40 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + * Fixed errno handling by Ulrich Drepper . + */ + +#include + +ENTRY(__cosl) + fldt 8(%rsp) + fxam + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 3f +4: fcos + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret + .align ALIGNARG(4) +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fcos + ret +3: //call __errno_location@PLT + //movl $EDOM, (%rax) + jmp 4b +END (__cosl) +weak_alias (__cosl, cosl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_expm1l.S b/src/system/libroot/posix/glibc/arch/x86_64/s_expm1l.S new file mode 100644 index 0000000000..eeffc3ebf5 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_expm1l.S @@ -0,0 +1,89 @@ +/* ix87 specific implementation of exp(x)-1. + Copyright (C) 1996,1997,2001,2002,2008,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + Based on code by John C. Bowman . + Corrections by H.J. Lu (hjl@gnu.ai.mit.edu), 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Using: e^x - 1 = 2^(x * log2(e)) - 1 */ + +#include + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + ASM_TYPE_DIRECTIVE(minus1,@object) +minus1: .double -1.0 + ASM_SIZE_DIRECTIVE(minus1) + ASM_TYPE_DIRECTIVE(one,@object) +one: .double 1.0 + ASM_SIZE_DIRECTIVE(one) + ASM_TYPE_DIRECTIVE(l2e,@object) +l2e: .tfloat 1.442695040888963407359924681002 + ASM_SIZE_DIRECTIVE(l2e) + +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__expm1l) + movzwl 8+8(%rsp), %eax // load sign bit and 15-bit exponent + xorb $0x80, %ah // invert sign bit (now 1 is "positive") + cmpl $0xc006, %eax // is num positive and exp >= 6 (number is >= 128.0)? + jae __expl@PLT // (if num is denormal, it is at least >= 64.0) + + fldt 8(%rsp) // x + fxam // Is NaN or +-Inf? + fstsw %ax + movb $0x45, %ch + andb %ah, %ch + cmpb $0x40, %ch + je 3f // If +-0, jump. + cmpb $0x05, %ch + je 2f // If +-Inf, jump. + + fldt MO(l2e) // log2(e) : x + fmulp // log2(e)*x + fld %st // log2(e)*x : log2(e)*x + frndint // int(log2(e)*x) : log2(e)*x + fsubr %st, %st(1) // int(log2(e)*x) : fract(log2(e)*x) + fxch // fract(log2(e)*x) : int(log2(e)*x) + f2xm1 // 2^fract(log2(e)*x)-1 : int(log2(e)*x) + fscale // 2^(log2(e)*x)-2^int(log2(e)*x) : int(log2(e)*x) + fxch // int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fldl MO(one) // 1 : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fscale // 2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fsubrl MO(one) // 1-2^int(log2(e)*x) : int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fstp %st(1) // 1-2^int(log2(e)*x) : 2^(log2(e)*x)-2^int(log2(e)*x) + fsubrp %st, %st(1) // 2^(log2(e)*x)-1 + ret + +2: testl $0x200, %eax // Test sign. + jz 3f // If positive, jump. + fstp %st + fldl MO(minus1) // Set result to -1.0. +3: ret +END(__expm1l) +libm_hidden_def (__expm1l) +weak_alias (__expm1l, expm1l) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fabs.c b/src/system/libroot/posix/glibc/arch/x86_64/s_fabs.c new file mode 100644 index 0000000000..e5f70b7844 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fabs.c @@ -0,0 +1,27 @@ +/* Absolute value of floating point number. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +double +__fabs (double x) +{ + return __builtin_fabs (x); +} +weak_alias (__fabs, fabs) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fabsf.c b/src/system/libroot/posix/glibc/arch/x86_64/s_fabsf.c new file mode 100644 index 0000000000..5e58c11310 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fabsf.c @@ -0,0 +1,27 @@ +/* Absolute value of floating point number. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +float +__fabsf (float x) +{ + return __builtin_fabsf (x); +} +weak_alias (__fabsf, fabsf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fabsl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fabsl.S new file mode 100644 index 0000000000..3bee0f244e --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fabsl.S @@ -0,0 +1,28 @@ +/* Absolute value of floating point number. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fabsl) + fldt 8(%rsp) + fabs + ret +END(__fabsl) +weak_alias (__fabsl, fabsl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fdiml.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fdiml.S new file mode 100644 index 0000000000..d63ca00ef1 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fdiml.S @@ -0,0 +1,44 @@ +/* Compute positive difference. + Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fdiml) + fldt 8(%rsp) // x + fldt 24(%rsp) // x : y + + fucomi %st(1), %st + jp 1f + + jc 3f + fstp %st(1) + fldz + jmp 2f + +3: fsubrp %st, %st(1) + ret + +1: fucomi %st(0), %st + fcmovnu %st(1), %st +2: fstp %st(1) + ret +END(__fdiml) +weak_alias (__fdiml, fdiml) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_finitel.S b/src/system/libroot/posix/glibc/arch/x86_64/s_finitel.S new file mode 100644 index 0000000000..9e49796901 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_finitel.S @@ -0,0 +1,16 @@ +/* + * Written by Joe Keane . + * Adopted for x86-64 by Andreas Jaeger . + */ + +#include + +ENTRY(__finitel) + movl 16(%rsp),%eax + orl $0xffff8000, %eax + incl %eax + shrl $31, %eax + ret +END (__finitel) +weak_alias (__finitel, finitel) +hidden_def (__finitel) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_floorl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_floorl.S new file mode 100644 index 0000000000..f9ecc388df --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_floorl.S @@ -0,0 +1,30 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Changes for x86-64 by Andreas Jaeger =09 + * Public domain. + */ + +#include + +ENTRY(__floorl) + fldt 8(%rsp) + + fstcw -4(%rsp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl -4(%rsp),%edx + andl $0xf7ff,%edx + movl %edx,-8(%rsp) + fldcw -8(%rsp) /* load modified control word */ + + frndint /* round */ + + fldcw -4(%rsp) /* restore original control word */ + + ret +END (__floorl) +weak_alias (__floorl, floorl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fmax.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fmax.S new file mode 100644 index 0000000000..b55d6f84ce --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fmax.S @@ -0,0 +1,36 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fmax) + ucomisd %xmm0, %xmm1 + jp 1f // jump if unordered + maxsd %xmm1, %xmm0 + jmp 2f + +1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN? + jp 2f // then return xmm0 + movsd %xmm1, %xmm0 // otherwise return xmm1 + +2: ret +END(__fmax) +weak_alias (__fmax, fmax) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxf.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxf.S new file mode 100644 index 0000000000..20d6fdd065 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxf.S @@ -0,0 +1,36 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fmaxf) + ucomiss %xmm0, %xmm1 + jp 1f // jump if unordered + maxss %xmm1, %xmm0 + jmp 2f + +1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN? + jp 2f // then return xmm0 + movss %xmm1, %xmm0 // otherwise return xmm1 + +2: ret +END(__fmaxf) +weak_alias (__fmaxf, fmaxf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxl.S new file mode 100644 index 0000000000..557ef3a17c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fmaxl.S @@ -0,0 +1,40 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fmaxl) + fldt 8(%rsp) // x + fldt 24(%rsp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fxch + + fucomi %st(1), %st + fcmovb %st(1), %st + + fstp %st(1) + + ret +END(__fmaxl) +weak_alias (__fmaxl, fmaxl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fmin.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fmin.S new file mode 100644 index 0000000000..37a3daaab2 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fmin.S @@ -0,0 +1,36 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fmin) + ucomisd %xmm0, %xmm1 + jp 1f // jump if unordered + minsd %xmm1, %xmm0 + jmp 2f + +1: ucomisd %xmm1, %xmm1 // Is xmm1 a NaN? + jp 2f // then return xmm0 + movsd %xmm1, %xmm0 // otherwise return xmm1 + +2: ret +END(__fmin) +weak_alias (__fmin, fmin) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fminf.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fminf.S new file mode 100644 index 0000000000..8e6f04bc08 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fminf.S @@ -0,0 +1,36 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fminf) + ucomiss %xmm0, %xmm1 + jp 1f // jump if unordered + minss %xmm1, %xmm0 + jmp 2f + +1: ucomiss %xmm1, %xmm1 // Is xmm1 a NaN? + jp 2f // then return xmm0 + movss %xmm1, %xmm0 // otherwise return xmm1 + +2: ret +END(__fminf) +weak_alias (__fminf, fminf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fminl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_fminl.S new file mode 100644 index 0000000000..cbe58f1b25 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fminl.S @@ -0,0 +1,38 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__fminl) + fldt 8(%rsp) // x + fldt 24(%rsp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fucomi %st(1), %st + fcmovnb %st(1), %st + + fstp %st(1) + + ret +END(__fminl) +weak_alias (__fminl, fminl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_fpclassifyl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_fpclassifyl.c new file mode 100644 index 0000000000..679e721d38 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_fpclassifyl.c @@ -0,0 +1,43 @@ +/* Return classification value corresponding to argument. + Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + + +int +__fpclassifyl (long double x) +{ + u_int32_t ex, hx, lx; + int retval = FP_NORMAL; + + GET_LDOUBLE_WORDS (ex, hx, lx, x); + ex &= 0x7fff; + if ((ex | lx | hx) == 0) + retval = FP_ZERO; + else if (ex == 0 && (hx & 0x80000000) == 0) + retval = FP_SUBNORMAL; + else if (ex == 0x7fff) + retval = ((hx & 0x7fffffff) | lx) != 0 ? FP_NAN : FP_INFINITE; + + return retval; +} +libm_hidden_def (__fpclassifyl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_ilogbl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_ilogbl.S new file mode 100644 index 0000000000..f59040c11e --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_ilogbl.S @@ -0,0 +1,35 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Adapted for x86-64 by Andreas Jaeger . + * Public domain. + */ + +#include + +ENTRY(__ilogbl) + fldt 8(%rsp) +/* I added the following ugly construct because ilogb(+-Inf) is + required to return INT_MAX in ISO C99. + -- jakub@redhat.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + + fxtract + fstp %st + + fistpl -4(%rsp) + fwait + movl -4(%rsp),%eax + + ret + +1: fstp %st + movl $0x7fffffff, %eax + ret +END (__ilogbl) +weak_alias (__ilogbl, ilogbl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_isinfl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_isinfl.c new file mode 100644 index 0000000000..72e4ae8138 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_isinfl.c @@ -0,0 +1,37 @@ +/* + * Written by J.T. Conklin . + * Change for long double by Ulrich Drepper . + * Intel i387 specific version. + * Public domain. + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* + * isinfl(x) returns 1 if x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + int __isinfl(long double x) +#else + int __isinfl(x) + long double x; +#endif +{ + int32_t se,hx,lx; + GET_LDOUBLE_WORDS(se,hx,lx,x); + /* This additional ^ 0x80000000 is necessary because in Intel's + internal representation of the implicit one is explicit. */ + lx |= (hx ^ 0x80000000) | ((se & 0x7fff) ^ 0x7fff); + lx |= -lx; + se &= 0x8000; + return ~(lx >> 31) & (1 - (se >> 14)); +} +hidden_def (__isinfl) +weak_alias (__isinfl, isinfl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_isnanl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_isnanl.c new file mode 100644 index 0000000000..aa459956e9 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_isnanl.c @@ -0,0 +1,48 @@ +/* s_isnanl.c -- long double version for i387 of s_isnan.c. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* + * isnanl(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + int __isnanl(long double x) +#else + int __isnanl(x) + long double x; +#endif +{ + int32_t se,hx,lx; + GET_LDOUBLE_WORDS(se,hx,lx,x); + se = (se & 0x7fff) << 1; + /* The additional & 0x7fffffff is required because Intel's + extended format has the normally implicit 1 explicit + present. Sigh! */ + lx |= hx & 0x7fffffff; + se |= (u_int32_t)(lx|(-lx))>>31; + se = 0xfffe - se; + return (int)((u_int32_t)(se))>>16; +} +hidden_def (__isnanl) +weak_alias (__isnanl, isnanl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_llrint.S b/src/system/libroot/posix/glibc/arch/x86_64/s_llrint.S new file mode 100644 index 0000000000..d496e4685c --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_llrint.S @@ -0,0 +1,31 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__llrint) + cvtsd2si %xmm0,%rax + ret +END(__llrint) +weak_alias (__llrint, llrint) +strong_alias (__llrint, __lrint) +weak_alias (__llrint, lrint) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_llrintf.S b/src/system/libroot/posix/glibc/arch/x86_64/s_llrintf.S new file mode 100644 index 0000000000..2e818b70a1 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_llrintf.S @@ -0,0 +1,31 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__llrintf) + cvtss2si %xmm0,%rax + ret +END(__llrintf) +weak_alias (__llrintf, llrintf) +strong_alias (__llrintf, __lrintf) +weak_alias (__llrintf, lrintf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_llrintl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_llrintl.S new file mode 100644 index 0000000000..2886dbe499 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_llrintl.S @@ -0,0 +1,34 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +ENTRY(__llrintl) + fldt 8(%rsp) + fistpll -8(%rsp) + fwait + movq -8(%rsp),%rax + ret +END(__llrintl) +weak_alias (__llrintl, llrintl) +strong_alias (__llrintl, __lrintl) +weak_alias (__llrintl, lrintl) + diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_log1pl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_log1pl.S new file mode 100644 index 0000000000..ac2bd22a4f --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_log1pl.S @@ -0,0 +1,72 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + */ + +#include + +RCSID("$NetBSD: s_log1p.S,v 1.7 1995/05/09 00:10:58 jtc Exp $") + +#ifdef __ELF__ + .section .rodata +#else + .text +#endif + .align ALIGNARG(4) + /* The fyl2xp1 can only be used for values in + -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + 0.29 is a safe value. + */ +limit: .tfloat 0.29 + /* Please note: we use a double value here. Since 1.0 has + an exact representation this does not effect the accuracy + but it helps to optimize the code. */ +one: .double 1.0 + +/* + * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, + * otherwise fyl2x with the needed extra computation. + */ +#ifdef PIC +#define MO(op) op##(%rip) +#else +#define MO(op) op +#endif + + .text +ENTRY(__log1pl) + fldln2 + + fldt 8(%rsp) + + fxam + fnstsw + fld %st + testb $1, %ah + jnz 3f // in case x is NaN or ±Inf +4: + fabs + fldt MO(limit) + fcompp + fnstsw + andb $1,%ah + jz 2f + + faddl MO(one) + fyl2x + ret + +2: fyl2xp1 + ret + +3: testb $4, %ah + jnz 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret + +END (__log1pl) +weak_alias (__log1pl, log1pl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_logbl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_logbl.c new file mode 100644 index 0000000000..34cfb01ecc --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_logbl.c @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include "math_private.h" + +long double +__logbl (long double x) +{ + long double res; + + asm ("fxtract\n" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +} + +weak_alias (__logbl, logbl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_lrint.S b/src/system/libroot/posix/glibc/arch/x86_64/s_lrint.S new file mode 100644 index 0000000000..dfc31359a0 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_lrint.S @@ -0,0 +1 @@ +/* Not needed, see s_llrint.S. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_lrintf.S b/src/system/libroot/posix/glibc/arch/x86_64/s_lrintf.S new file mode 100644 index 0000000000..fcdc4dca9a --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_lrintf.S @@ -0,0 +1 @@ +/* Not needed, see s_llrintf.S. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_lrintl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_lrintl.S new file mode 100644 index 0000000000..ef9c45d00d --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_lrintl.S @@ -0,0 +1 @@ +/* Not needed, see s_llrintl.S. */ diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_nearbyintl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_nearbyintl.S new file mode 100644 index 0000000000..dab2750a23 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_nearbyintl.S @@ -0,0 +1,21 @@ +/* + * Written by J.T. Conklin . + * Public domain. + */ +/* Adapted for use as nearbyint by Ulrich Drepper . */ + +#include + +ENTRY(__nearbyintl) + fldt 8(%rsp) + fnstcw -4(%rsp) + movl -4(%rsp), %eax + orl $0x20, %eax + movl %eax, -8(%rsp) + fldcw -8(%rsp) + frndint + fclex + fldcw -4(%rsp) + ret +END (__nearbyintl) +weak_alias (__nearbyintl, nearbyintl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_nextafterl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_nextafterl.c new file mode 100644 index 0000000000..ed75406c0f --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_nextafterl.c @@ -0,0 +1,124 @@ +/* s_nextafterl.c -- long double version of s_nextafter.c. + * Special version for i387. + * Conversion to long double by Ulrich Drepper, + * Cygnus Support, drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* IEEE functions + * nextafterl(x,y) + * return the next machine floating-point number of x in the + * direction toward y. + * Special cases: + */ + +#include "math.h" +#include "math_private.h" + +#ifdef __STDC__ + long double __nextafterl(long double x, long double y) +#else + long double __nextafterl(x,y) + long double x,y; +#endif +{ + u_int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + int32_t esx,esy; + + GET_LDOUBLE_WORDS(esx,hx,lx,x); + GET_LDOUBLE_WORDS(esy,hy,ly,y); + ix = esx&0x7fff; /* |x| */ + iy = esy&0x7fff; /* |y| */ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + if(((ix==0x7fff)&&(((hx&0x7fffffff)|lx)!=0)) || /* x is nan */ + ((iy==0x7fff)&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */ + return x+y; + if(x==y) return y; /* x=y, return y */ + if((ix|hx|lx)==0) { /* x == 0 */ + long double u; + SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */ + u = math_opt_barrier (x); + u = u * u; + math_force_eval (u); /* raise underflow flag */ + return x; + } + if(esx>=0) { /* x > 0 */ + if(esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))) { + /* x > y, x -= ulp */ + if(lx==0) { + if (hx <= 0x80000000) { + if (esx == 0) { + --hx; + } else { + esx -= 1; + hx = hx - 1; + if (esx > 0) + hx |= 0x80000000; + } + } else + hx -= 1; + } + lx -= 1; + } else { /* x < y, x += ulp */ + lx += 1; + if(lx==0) { + hx += 1; + if (hx==0 || (esx == 0 && hx == 0x80000000)) { + esx += 1; + hx |= 0x80000000; + } + } + } + } else { /* x < 0 */ + if(esy>=0||(esx>esy||((esx==esy)&&(hx>hy||((hx==hy)&&(lx>ly)))))){ + /* x < y, x -= ulp */ + if(lx==0) { + if (hx <= 0x80000000) { + esx -= 1; + hx = hx - 1; + if ((esx&0x7fff) > 0) + hx |= 0x80000000; + } else + hx -= 1; + } + lx -= 1; + } else { /* x > y, x += ulp */ + lx += 1; + if(lx==0) { + hx += 1; + if (hx==0 || (esx == 0xffff8000 && hx == 0x80000000)) { + esx += 1; + hx |= 0x80000000; + } + } + } + } + esy = esx&0x7fff; + if(esy==0x7fff) return x+x; /* overflow */ + if(esy==0) { + long double u = x*x; /* underflow */ + math_force_eval (u); /* raise underflow flag */ + } + SET_LDOUBLE_WORDS(x,esx,hx,lx); + return x; +} +weak_alias (__nextafterl, nextafterl) +strong_alias (__nextafterl, __nexttowardl) +weak_alias (__nextafterl, nexttowardl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_nexttoward.c b/src/system/libroot/posix/glibc/arch/x86_64/s_nexttoward.c new file mode 100644 index 0000000000..529069c534 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_nexttoward.c @@ -0,0 +1,107 @@ +/* s_nexttoward.c + * Special i387 version + * Conversion from s_nextafter.c by Ulrich Drepper, Cygnus Support, + * drepper@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +/* IEEE functions + * nexttoward(x,y) + * return the next machine floating-point number of x in the + * direction toward y. + * Special cases: + */ + +#include "math.h" +#include "math_private.h" +#include + +#ifdef __STDC__ + double __nexttoward(double x, long double y) +#else + double __nexttoward(x,y) + double x; + long double y; +#endif +{ + int32_t hx,ix,iy; + u_int32_t lx,hy,ly,esy; + + EXTRACT_WORDS(hx,lx,x); + GET_LDOUBLE_WORDS(esy,hy,ly,y); + ix = hx&0x7fffffff; /* |x| */ + iy = esy&0x7fff; /* |y| */ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ + ((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0)) /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ + if((ix|lx)==0) { /* x == 0 */ + double u; + INSERT_WORDS(x,(esy&0x8000)<<16,1); /* return +-minsub */ + u = math_opt_barrier (x); + u = u * u; + math_force_eval (u); /* raise underflow flag */ + return x; + } + if(hx>=0) { /* x > 0 */ + if (esy>=0x8000||((ix>>20)&0x7ff)>iy-0x3c00 + || (((ix>>20)&0x7ff)==iy-0x3c00 + && (((hx<<11)|(lx>>21))>(hy&0x7fffffff) + || (((hx<<11)|(lx>>21))==(hy&0x7fffffff) + && (lx<<11)>ly)))) { /* x > y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x < y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } else { /* x < 0 */ + if (esy<0x8000||((ix>>20)&0x7ff)>iy-0x3c00 + || (((ix>>20)&0x7ff)==iy-0x3c00 + && (((hx<<11)|(lx>>21))>(hy&0x7fffffff) + || (((hx<<11)|(lx>>21))==(hy&0x7fffffff) + && (lx<<11)>ly)))) {/* x < y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x > y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) { + x = x+x; /* overflow */ + if (FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1) + /* Force conversion to double. */ + asm ("" : "+m"(x)); + return x; + } + if(hy<0x00100000) { + double u = x*x; /* underflow */ + math_force_eval (u); /* raise underflow flag */ + } + INSERT_WORDS(x,hx,lx); + return x; +} +weak_alias (__nexttoward, nexttoward) +#ifdef NO_LONG_DOUBLE +strong_alias (__nexttoward, __nexttowardl) +weak_alias (__nexttoward, nexttowardl) +#endif diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_nexttowardf.c b/src/system/libroot/posix/glibc/arch/x86_64/s_nexttowardf.c new file mode 100644 index 0000000000..87c44a827d --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_nexttowardf.c @@ -0,0 +1,87 @@ +/* s_nexttowardf.c -- float version of s_nextafter.c. + * Special i387 version. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#if defined(LIBM_SCCS) && !defined(lint) +static char rcsid[] = "$NetBSD: $"; +#endif + +#include "math.h" +#include "math_private.h" +#include + +#ifdef __STDC__ + float __nexttowardf(float x, long double y) +#else + float __nexttowardf(x,y) + float x; + long double y; +#endif +{ + int32_t hx,ix,iy; + u_int32_t hy,ly,esy; + + GET_FLOAT_WORD(hx,x); + GET_LDOUBLE_WORDS(esy,hy,ly,y); + ix = hx&0x7fffffff; /* |x| */ + iy = esy&0x7fff; /* |y| */ + + /* Intel's extended format has the normally implicit 1 explicit + present. Sigh! */ + if((ix>0x7f800000) || /* x is nan */ + (iy>=0x7fff&&(((hy&0x7fffffff)|ly)!=0))) /* y is nan */ + return x+y; + if((long double) x==y) return y; /* x=y, return y */ + if(ix==0) { /* x == 0 */ + float u; + SET_FLOAT_WORD(x,((esy&0x8000)<<16)|1);/* return +-minsub*/ + u = math_opt_barrier (x); + u = u * u; + math_force_eval (u); /* raise underflow flag */ + return x; + } + if(hx>=0) { /* x > 0 */ + if(esy>=0x8000||((ix>>23)&0xff)>iy-0x3f80 + || (((ix>>23)&0xff)==iy-0x3f80 + && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x > y, x -= ulp */ + hx -= 1; + } else { /* x < y, x += ulp */ + hx += 1; + } + } else { /* x < 0 */ + if(esy<0x8000||((ix>>23)&0xff)>iy-0x3f80 + || (((ix>>23)&0xff)==iy-0x3f80 + && ((ix&0x7fffff)<<8)>(hy&0x7fffffff))) {/* x < y, x -= ulp */ + hx -= 1; + } else { /* x > y, x += ulp */ + hx += 1; + } + } + hy = hx&0x7f800000; + if(hy>=0x7f800000) { + x = x+x; /* overflow */ + if (FLT_EVAL_METHOD != 0) + /* Force conversion to float. */ + asm ("" : "+m"(x)); + return x; + } + if(hy<0x00800000) { + float u = x*x; /* underflow */ + math_force_eval (u); /* raise underflow flag */ + } + SET_FLOAT_WORD(x,hx); + return x; +} +weak_alias (__nexttowardf, nexttowardf) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_rintl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_rintl.c new file mode 100644 index 0000000000..874e32baf3 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_rintl.c @@ -0,0 +1,18 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include "math_private.h" + +long double +__rintl (long double x) +{ + long double res; + + asm ("frndint" : "=t" (res) : "0" (x)); + return res; +} + +weak_alias (__rintl, rintl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_scalbnl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_scalbnl.S new file mode 100644 index 0000000000..d0e9301eed --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_scalbnl.S @@ -0,0 +1,18 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Changes for x86-64 by Andreas Jaeger =09 + * Public domain. + */ + +#include + +ENTRY(__scalbnl) + movl %edi,-4(%rsp) + fildl -4(%rsp) + fldt 8(%rsp) + fscale + fstp %st(1) + ret +END (__scalbnl) +weak_alias (__scalbnl, scalbnl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_significandl.c b/src/system/libroot/posix/glibc/arch/x86_64/s_significandl.c new file mode 100644 index 0000000000..22a29c67cb --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_significandl.c @@ -0,0 +1,19 @@ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include "math_private.h" + +long double +__significandl (long double x) +{ + long double res; + + asm ("fxtract\n" + "fstp %%st(1)" : "=t" (res) : "0" (x)); + return res; +} + +weak_alias (__significandl, significandl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_sincos.S b/src/system/libroot/posix/glibc/arch/x86_64/s_sincos.S new file mode 100644 index 0000000000..9a33615340 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_sincos.S @@ -0,0 +1,61 @@ +/* Compute sine and cosine of argument. + Copyright (C) 1997, 2000, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define ANGLE PARMS +#define SINP ANGLE+12 +#define COSP SINP+PTR_SIZE + + .text +ENTRY (BP_SYM (__sincos)) + ENTER + + movsd %xmm0, -8(%rsp) + fldl -8(%rsp) + fsincos + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstpl (%rsi) + fstpl (%rdi) + + LEAVE + retq + +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsincos + fstpl (%rsi) + fstpl (%rdi) + + LEAVE + retq +END (BP_SYM (__sincos)) +weak_alias (BP_SYM (__sincos), BP_SYM (sincos)) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_sincosl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_sincosl.S new file mode 100644 index 0000000000..b17eabe767 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_sincosl.S @@ -0,0 +1,60 @@ +/* Compute sine and cosine of argument. + Copyright (C) 1997, 2000, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define ANGLE PARMS +#define SINP ANGLE+12 +#define COSP SINP+PTR_SIZE + + .text +ENTRY (BP_SYM (__sincosl)) + ENTER + + fldt 8(%rsp) + fsincos + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstpt (%rsi) + fstpt (%rdi) + + LEAVE + retq + +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsincos + fstpt (%rsi) + fstpt (%rdi) + + LEAVE + retq +END (BP_SYM (__sincosl)) +weak_alias (BP_SYM (__sincosl), BP_SYM (sincosl)) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_sinl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_sinl.S new file mode 100644 index 0000000000..54577b04d6 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_sinl.S @@ -0,0 +1,40 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + * Fixed errno handling by Ulrich Drepper . + */ + +#include + +ENTRY(__sinl) + fldt 8(%rsp) + fxam + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 3f +4: fsin + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret + .align ALIGNARG(4) +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsin + ret +3: //call __errno_location@PLT + //movl $EDOM, (%rax) + jmp 4b +END (__sinl) +weak_alias (__sinl, sinl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_tanl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_tanl.S new file mode 100644 index 0000000000..4a704203cd --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_tanl.S @@ -0,0 +1,43 @@ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for `long double' by Ulrich Drepper . + * Adapted for x86-64 by Andreas Jaeger . + * Fixed errno handling by Ulrich Drepper . + */ + +#include + +RCSID("$NetBSD: $") + +ENTRY(__tanl) + fldt 8(%rsp) + fxam + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 3f +4: fptan + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstp %st(0) + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fptan + fstp %st(0) + ret +3: //call __errno_location@PLT + //movl $EDOM, (%rax) + jmp 4b +END (__tanl) +weak_alias (__tanl, tanl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/s_truncl.S b/src/system/libroot/posix/glibc/arch/x86_64/s_truncl.S new file mode 100644 index 0000000000..61acf9a250 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/s_truncl.S @@ -0,0 +1,34 @@ +/* Truncate long double value. + Copyright (C) 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +ENTRY(__truncl) + fldt 8(%rsp) + fstcw -4(%rsp) + movl $0xc00, %edx + orl -4(%rsp), %edx + movl %edx, -8(%rsp) + fldcw -8(%rsp) + frndint + fldcw -4(%rsp) + ret +END(__truncl) +weak_alias (__truncl, truncl) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/sub_n.S b/src/system/libroot/posix/glibc/arch/x86_64/sub_n.S new file mode 100644 index 0000000000..48e1a2e0f4 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/sub_n.S @@ -0,0 +1,42 @@ +/* AMD64 __mpn_sub_n -- Add two limb vectors of the same length > 0 and store + sum in a third limb vector. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY (__mpn_sub_n) + leaq (%rsi,%rcx,8), %rsi + leaq (%rdi,%rcx,8), %rdi + leaq (%rdx,%rcx,8), %rdx + negq %rcx + xorl %eax, %eax # clear cy + .p2align 2 +L(loop): + movq (%rsi,%rcx,8), %rax + movq (%rdx,%rcx,8), %r10 + sbbq %r10, %rax + movq %rax, (%rdi,%rcx,8) + incq %rcx + jne L(loop) + movq %rcx, %rax # zero %rax + adcq %rax, %rax + ret +END (__mpn_sub_n) diff --git a/src/system/libroot/posix/glibc/arch/x86_64/submul_1.S b/src/system/libroot/posix/glibc/arch/x86_64/submul_1.S new file mode 100644 index 0000000000..e94c9a7bee --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/x86_64/submul_1.S @@ -0,0 +1,46 @@ +/* AMD64 __mpn_submul_1 -- Multiply a limb vector with a limb and subtract + the result from a second limb vector. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" + + .text +ENTRY (__mpn_submul_1) + movq %rdx, %r11 + leaq (%rsi,%r11,8), %rsi + leaq (%rdi,%r11,8), %rdi + negq %r11 + xorl %r8d, %r8d + .p2align 3 +L(loop): + movq (%rsi,%r11,8), %rax + movq (%rdi,%r11,8), %r10 + mulq %rcx + subq %r8, %r10 + movl $0, %r8d + adcl %r8d, %r8d + subq %rax, %r10 + adcq %rdx, %r8 + movq %r10, (%rdi,%r11,8) + incq %r11 + jne L(loop) + movq %r8, %rax + ret +END (__mpn_submul_1) diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/asm-syntax.h b/src/system/libroot/posix/glibc/include/arch/x86_64/asm-syntax.h new file mode 100644 index 0000000000..98eb26c121 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/asm-syntax.h @@ -0,0 +1,24 @@ +/* Definitions for x86 syntax variations. + Copyright (C) 1992,1994,1995,1997,2000,2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in the GNU MP Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#undef ALIGN +#define ALIGN(log) .align 1< directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +#include + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +#else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +#endif + + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#if defined __GNUC__ && __GNUC__ >= 2 +# if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__ \ + || defined __pentiumpro__ || defined __pentium4__ \ + || defined __k8__ || defined __athlon__ \ + || defined __k6__) +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (__x) \ + : "cc"); \ + __v; })) +# endif +#else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# if __WORDSIZE == 64 +# define __bswap_64(x) \ + (__extension__ \ + ({ register unsigned long __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_64 (__x); \ + else \ + __asm__ ("bswap %q0" : "=r" (__v) : "0" (__x)); \ + __v; })) +# else +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +# endif +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/endian.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/endian.h new file mode 100644 index 0000000000..2f59eada25 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/endian.h @@ -0,0 +1,7 @@ +/* x86_64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenv.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenv.h new file mode 100644 index 0000000000..3b3254bdd3 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenv.h @@ -0,0 +1,93 @@ +/* Copyright (C) 1997-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by the `fstenv' + instruction and has additional fields for the contents of the MXCSR + register as written by the `stmxcsr' instruction. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +#ifdef __x86_64__ + unsigned int __mxcsr; +#endif + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((const fenv_t *) -2) +#endif diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenvinline.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenvinline.h new file mode 100644 index 0000000000..42f77b5618 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/fenvinline.h @@ -0,0 +1,8 @@ +/* This file provides inline versions of floating-pint environment + handling functions. If there were any. */ + +#ifndef __NO_MATH_INLINES + +/* Here is where the code would go. */ + +#endif diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/huge_val.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/huge_val.h new file mode 100644 index 0000000000..f2bddf2874 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/huge_val.h @@ -0,0 +1,40 @@ +/* Stub `HUGE_VAL' constant. + Used by and functions for overflow. + Copyright (C) 1992, 1996, 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#else +# define HUGE_VAL 1e37 +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALF (__builtin_huge_valf()) +#else +# define HUGE_VALF 1e37f +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#else +# define HUGE_VALL ((long double) HUGE_VAL) +#endif diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathdef.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathdef.h new file mode 100644 index 0000000000..19d1fcaa7a --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathdef.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2001-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The x86-64 architecture computes values with the precission of the + used type. Similarly for -m32 -mfpmath=sse. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated + as `double'. */ + +#define FLT_EVAL_METHOD 0 + +#if __GNUC_PREREQ(3,3) +# define INFINITY (__builtin_inff()) +#else +# define INFINITY HUGE_VALF +#endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +/* The GCC 4.6 compiler will define __FP_FAST_FMA{,F,L} if the fma{,f,l} + builtins are supported. */ +# if __FP_FAST_FMA +# define FP_FAST_FMA 1 +# endif + +# if __FP_FAST_FMAF +# define FP_FAST_FMAF 1 +# endif + +# if __FP_FAST_FMAL +# define FP_FAST_FMAL 1 +# endif + +#endif /* ISO C99 */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathinline.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathinline.h new file mode 100644 index 0000000000..80f6d6453e --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/mathinline.h @@ -0,0 +1,970 @@ +/* Inline math functions for i387 and SSE. + Copyright (C) 1995-2012 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#define __NTH(fct) __attribute__ ((__nothrow__)) fct + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 +/* GCC 2.97 and up have builtins that actually can be used. */ +# if !__GNUC_PREREQ (2,97) +/* ISO C99 defines some macros to perform unordered comparisons. The + ix87 FPU supports this with special opcodes and we should use them. + These must not be inline functions since we have to be able to handle + all floating-point types. */ +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# ifdef __i686__ +/* For the PentiumPro and more recent processors we can provide + better code. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setne %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# else +/* This is the dumb, portable code for i386 and above. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; sahf; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) +# endif /* __i686__ */ +# endif /* GCC 2.97 */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +__BEGIN_NAMESPACE_C99 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__signbitf (float __x) +{ +# ifdef __SSE2_MATH__ + int __m; + __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); + return (__m & 0x8) != 0; +# else + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +# endif +} +__MATH_INLINE int +__signbit (double __x) +{ +# ifdef __SSE2_MATH__ + int __m; + __asm ("pmovmskb %1, %0" : "=r" (__m) : "x" (__x)); + return (__m & 0x80) != 0; +# else + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +# endif +} +__MATH_INLINE int +__signbitl (long double __x) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} + +__END_NAMESPACE_C99 +# endif +#endif + + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +#if __GNUC_PREREQ (2, 8) +# if !__GNUC_PREREQ (3, 4) && !defined __NO_MATH_INLINES \ + && defined __OPTIMIZE__ +/* GCC 3.4 introduced builtins for all functions below, so + there's no need to define any of these inline functions. */ + +# ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +/* Round to nearest integer. */ +# ifdef __SSE_MATH__ +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + long int __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); + return __res; +} +# endif +# ifdef __SSE2_MATH__ +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + long int __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); + return __res; +} +# endif +# ifdef __x86_64__ +__MATH_INLINE long long int +__NTH (llrintf (float __x)) +{ + long long int __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("cvtss2si %1, %0" : "=r" (__res) : "xm" (__x)); + return __res; +} +__MATH_INLINE long long int +__NTH (llrint (double __x)) +{ + long long int __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("cvtsd2si %1, %0" : "=r" (__res) : "xm" (__x)); + return __res; +} +# endif + +# if defined __FINITE_MATH_ONLY__ && __FINITE_MATH_ONLY__ > 0 \ + && defined __SSE2_MATH__ +/* Determine maximum of two values. */ +__MATH_INLINE float +__NTH (fmaxf (float __x, float __y)) +{ +# ifdef __AVX__ + float __res; + __asm ("vmaxss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); + return __res; +# else + __asm ("maxss %1, %0" : "+x" (__x) : "xm" (__y)); + return __x; +# endif +} +__MATH_INLINE double +__NTH (fmax (double __x, double __y)) +{ +# ifdef __AVX__ + float __res; + __asm ("vmaxsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); + return __res; +# else + __asm ("maxsd %1, %0" : "+x" (__x) : "xm" (__y)); + return __x; +# endif +} + +/* Determine minimum of two values. */ +__MATH_INLINE float +__NTH (fminf (float __x, float __y)) +{ +# ifdef __AVX__ + float __res; + __asm ("vminss %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); + return __res; +# else + __asm ("minss %1, %0" : "+x" (__x) : "xm" (__y)); + return __x; +# endif +} +__MATH_INLINE double +__NTH (fmin (double __x, double __y)) +{ +# ifdef __AVX__ + float __res; + __asm ("vminsd %2, %1, %0" : "=x" (__res) : "x" (x), "xm" (__y)); + return __res; +# else + __asm ("minsd %1, %0" : "+x" (__x) : "xm" (__y)); + return __x; +# endif +} +# endif + +__END_NAMESPACE_C99 +# endif + +# if defined __SSE4_1__ && defined __SSE2_MATH__ +# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +/* Round to nearest integer. */ +__MATH_INLINE double +__NTH (rint (double __x)) +{ + double __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("roundsd $4, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__MATH_INLINE float +__NTH (rintf (float __x)) +{ + float __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("roundss $4, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} + +# ifdef __USE_ISOC99 +/* Round to nearest integer without raising inexact exception. */ +__MATH_INLINE double +__NTH (nearbyint (double __x)) +{ + double __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("roundsd $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__MATH_INLINE float +__NTH (nearbyintf (float __x)) +{ + float __res; + /* Mark as volatile since the result is dependent on the state of + the SSE control register (the rounding mode). Otherwise GCC might + remove these assembler instructions since it does not know about + the rounding mode change and cannot currently be told. */ + __asm __volatile__ ("roundss $0xc, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +# endif + +__END_NAMESPACE_C99 +# endif + +__BEGIN_NAMESPACE_STD +/* Smallest integral value not less than X. */ +__MATH_INLINE double +__NTH (ceil (double __x)) +{ + double __res; + __asm ("roundsd $2, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__END_NAMESPACE_STD + +__BEGIN_NAMESPACE_C99 +__MATH_INLINE float +__NTH (ceilf (float __x)) +{ + float __res; + __asm ("roundss $2, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__END_NAMESPACE_C99 + +__BEGIN_NAMESPACE_STD +/* Largest integer not greater than X. */ +__MATH_INLINE double +__NTH (floor (double __x)) +{ + double __res; + __asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__END_NAMESPACE_STD + +__BEGIN_NAMESPACE_C99 +__MATH_INLINE float +__NTH (floorf (float __x)) +{ + float __res; + __asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" (__x)); + return __res; +} +__END_NAMESPACE_C99 +# endif +# endif +#endif + +#ifndef __x86_64__ +# if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__) + +/* The inline functions do not set errno or raise necessarily the + correct exceptions. */ +# undef math_errhandling + +/* A macro to define float, double, and long double versions of various + math functions for the ix87 FPU. FUNC is the function name (which will + be suffixed with f and l for the float and long double version, + respectively). OP is the name of the FPU operation. + We define two sets of macros. The set with the additional NP + doesn't add a prototype declaration. */ + +# if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) \ + __inline_mathop_ (float, __CONCAT(func,f), op) \ + __inline_mathop_ (long double, __CONCAT(func,l), op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) \ + __inline_mathopNP_ (float, __CONCAT(func,f), op) \ + __inline_mathopNP_ (long double, __CONCAT(func,l), op) +# else +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) +# endif + +# define __inline_mathop_(float_type, func, op) \ + __inline_mathop_decl_ (float_type, func, op, "0" (__x)) +# define __inline_mathopNP_(float_type, func, op) \ + __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) + + +# if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) \ + __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) \ + __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) +# else +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) +# endif + +# define __inline_mathop_decl_(float_type, func, op, params...) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathop_declNP_ (float_type, func, op, params) + +# define __inline_mathop_declNP_(float_type, func, op, params...) \ + __MATH_INLINE float_type __NTH (func (float_type __x)) \ + { \ + register float_type __result; \ + __asm __volatile__ (op : "=t" (__result) : params); \ + return __result; \ + } + + +# if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, arg, code) \ + __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, arg, code) \ + __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) \ + __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +# else +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, (arg), code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, (arg), code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) +# endif + +# define __inline_mathcode_(float_type, func, arg, code) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathcodeNP_(float_type, func, arg, code) + +# define __inline_mathcodeNP_(float_type, func, arg, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg)) \ + { \ + code; \ + } + + +# define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type func (float_type, float_type) __THROW; \ + __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) + +# define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ + { \ + code; \ + } + +# define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ + __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) + +# define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ + float_type arg3)) \ + { \ + code; \ + } +# endif + + +# if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ +/* Miscellaneous functions */ + +/* __FAST_MATH__ is defined by gcc -ffast-math. */ +# ifdef __FAST_MATH__ +# ifdef __USE_GNU +# define __sincos_code \ + register long double __cosr; \ + register long double __sinr; \ + register unsigned int __swtmp; \ + __asm __volatile__ \ + ("fsincos\n\t" \ + "fnstsw %w2\n\t" \ + "testl $0x400, %2\n\t" \ + "jz 1f\n\t" \ + "fldpi\n\t" \ + "fadd %%st(0)\n\t" \ + "fxch %%st(1)\n\t" \ + "2: fprem1\n\t" \ + "fnstsw %w2\n\t" \ + "testl $0x400, %2\n\t" \ + "jnz 2b\n\t" \ + "fstp %%st(1)\n\t" \ + "fsincos\n\t" \ + "1:" \ + : "=t" (__cosr), "=u" (__sinr), "=a" (__swtmp) : "0" (__x)); \ + *__sinx = __sinr; \ + *__cosx = __cosr + +__MATH_INLINE void +__NTH (__sincos (double __x, double *__sinx, double *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosf (float __x, float *__sinx, float *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) +{ + __sincos_code; +} +# endif + + +/* Optimized inline implementation, sometimes with reduced precision + and/or argument range. */ + +# if __GNUC_PREREQ (3, 5) +# define __expm1_code \ + register long double __temp; \ + __temp = __builtin_expm1l (__x); \ + return __temp ? __temp : __x +# else +# define __expm1_code \ + register long double __value; \ + register long double __exponent; \ + register long double __temp; \ + __asm __volatile__ \ + ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __asm __volatile__ \ + ("fscale # 2^int(x * log2(e))\n\t" \ + : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ + __temp -= 1.0; \ + __temp += __value; \ + return __temp ? __temp : __x +# endif +__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) + +# if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) +# else +# define __exp_code \ + register long double __value; \ + register long double __exponent; \ + __asm __volatile__ \ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __value += 1.0; \ + __asm __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__value), "u" (__exponent)); \ + return __value +__inline_mathcodeNP (exp, __x, __exp_code) +__inline_mathcodeNP_ (long double, __expl, __x, __exp_code) +# endif + + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (tan, __x, \ + register long double __value; \ + register long double __value2 __attribute__ ((__unused__)); \ + __asm __volatile__ \ + ("fptan" \ + : "=t" (__value2), "=u" (__value) : "0" (__x)); \ + return __value) +# endif +# endif /* __FAST_MATH__ */ + + +# if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, + return __builtin_atan2l (__y, __x)) +# else +# define __atan2_code \ + register long double __value; \ + __asm __volatile__ \ + ("fpatan" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ + return __value +# ifdef __FAST_MATH__ +__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) +# endif +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) +# endif + + +# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (fmod, __x, __y, \ + register long double __value; \ + __asm __volatile__ \ + ("1: fprem\n\t" \ + "fnstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ + return __value) +# endif + + +# ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3,3) +__inline_mathopNP (sqrt, "fsqrt") +__inline_mathopNP_ (long double, __sqrtl, "fsqrt") +# define __libc_sqrtl(n) __sqrtl (n) +# else +# define __libc_sqrtl(n) __builtin_sqrtl (n) +# endif +# endif + +# if __GNUC_PREREQ (2, 8) +__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) +# if defined __USE_MISC || defined __USE_ISOC99 +__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) +__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) +# endif +__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) +# else +__inline_mathop (fabs, "fabs") +__inline_mathop_ (long double, __fabsl, "fabs") +# endif + +# ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3, 4) +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (sin, "fsin") +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (cos, "fcos") + +__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") + +__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) +__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) +# endif + +# if !__GNUC_PREREQ (3, 4) +__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") +# endif +# endif /* __FAST_MATH__ */ + +__inline_mathcode_ (long double, __sgn1l, __x, \ + __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ + { __xld: __x }; \ + __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ + __n.__xi[1] = 0x80000000; \ + __n.__xi[0] = 0; \ + return __n.__xld) + + +# ifdef __FAST_MATH__ +/* The argument range of the inline version of sinhl is slightly reduced. */ +__inline_mathcodeNP (sinh, __x, \ + register long double __exm1 = __expm1l (__fabsl (__x)); \ + return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) + +__inline_mathcodeNP (cosh, __x, \ + register long double __ex = __expl (__x); \ + return 0.5 * (__ex + 1.0 / __ex)) + +__inline_mathcodeNP (tanh, __x, \ + register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ + return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) +# endif + +__inline_mathcodeNP (floor, __x, \ + register long double __value; \ + register int __ignore; \ + unsigned short int __cw; \ + unsigned short int __cwtmp; \ + __asm __volatile ("fnstcw %3\n\t" \ + "movzwl %3, %1\n\t" \ + "andl $0xf3ff, %1\n\t" \ + "orl $0x0400, %1\n\t" /* rounding down */ \ + "movw %w1, %2\n\t" \ + "fldcw %2\n\t" \ + "frndint\n\t" \ + "fldcw %3" \ + : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ + "=m" (__cw) \ + : "0" (__x)); \ + return __value) + +__inline_mathcodeNP (ceil, __x, \ + register long double __value; \ + register int __ignore; \ + unsigned short int __cw; \ + unsigned short int __cwtmp; \ + __asm __volatile ("fnstcw %3\n\t" \ + "movzwl %3, %1\n\t" \ + "andl $0xf3ff, %1\n\t" \ + "orl $0x0800, %1\n\t" /* rounding up */ \ + "movw %w1, %2\n\t" \ + "fldcw %2\n\t" \ + "frndint\n\t" \ + "fldcw %3" \ + : "=t" (__value), "=&q" (__ignore), "=m" (__cwtmp), \ + "=m" (__cw) \ + : "0" (__x)); \ + return __value) + +# ifdef __FAST_MATH__ +# define __ldexp_code \ + register long double __value; \ + __asm __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ + return __value + +__MATH_INLINE double +__NTH (ldexp (double __x, int __y)) +{ + __ldexp_code; +} +# endif + + +/* Optimized versions for some non-standardized functions. */ +# if defined __USE_ISOC99 || defined __USE_MISC + +# ifdef __FAST_MATH__ +__inline_mathcodeNP (expm1, __x, __expm1_code) + +/* We cannot rely on M_SQRT being defined. So we do it for ourself + here. */ +# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (log1p, __x, \ + register long double __value; \ + if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ + __value = logl (1.0 + __x); \ + else \ + __asm __volatile__ \ + ("fldln2\n\t" \ + "fxch\n\t" \ + "fyl2xp1" \ + : "=t" (__value) : "0" (__x) : "st(1)"); \ + return __value) +# endif + + +/* The argument range of the inline version of asinhl is slightly reduced. */ +__inline_mathcodeNP (asinh, __x, \ + register long double __y = __fabsl (__x); \ + return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ + * __sgn1l (__x))) + +__inline_mathcodeNP (acosh, __x, \ + return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) + +__inline_mathcodeNP (atanh, __x, \ + register long double __y = __fabsl (__x); \ + return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) + +/* The argument range of the inline version of hypotl is slightly reduced. */ +__inline_mathcodeNP2 (hypot, __x, __y, + return __libc_sqrtl (__x * __x + __y * __y)) + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP(logb, __x, \ + register long double __value; \ + register long double __junk; \ + __asm __volatile__ \ + ("fxtract\n\t" \ + : "=t" (__junk), "=u" (__value) : "0" (__x)); \ + return __value) +# endif + +# endif +# endif + +# ifdef __USE_ISOC99 +# ifdef __FAST_MATH__ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +__MATH_INLINE float +__NTH (ldexpf (float __x, int __y)) +{ + __ldexp_code; +} + +__MATH_INLINE long double +__NTH (ldexpl (long double __x, int __y)) +{ + __ldexp_code; +} + +__inline_mathopNP (rint, "frndint") +# endif /* __FAST_MATH__ */ + +# define __lrint_code \ + long int __lrintres; \ + __asm__ __volatile__ \ + ("fistpl %0" \ + : "=m" (__lrintres) : "t" (__x) : "st"); \ + return __lrintres +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrintl (long double __x)) +{ + __lrint_code; +} +# undef __lrint_code + +# define __llrint_code \ + long long int __llrintres; \ + __asm__ __volatile__ \ + ("fistpll %0" \ + : "=m" (__llrintres) : "t" (__x) : "st"); \ + return __llrintres +__MATH_INLINE long long int +__NTH (llrintf (float __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrint (double __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrintl (long double __x)) +{ + __llrint_code; +} +# undef __llrint_code + +# endif + + +# ifdef __USE_MISC + +# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (drem, __x, __y, \ + register double __value; \ + register int __clobbered; \ + __asm __volatile__ \ + ("1: fprem1\n\t" \ + "fstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ + return __value) +# endif + + +/* This function is used in the `isfinite' macro. */ +__MATH_INLINE int +__NTH (__finite (double __x)) +{ + return (__extension__ + (((((union { double __d; int __i[2]; }) {__d: __x}).__i[1] + | 0x800fffffu) + 1) >> 31)); +} + +# endif /* __USE_MISC */ + +/* Undefine some of the large macros which are not used anymore. */ +# undef __atan2_code +# ifdef __FAST_MATH__ +# undef __expm1_code +# undef __exp_code +# undef __sincos_code +# endif /* __FAST_MATH__ */ + +# endif /* __NO_MATH_INLINES */ + + +/* This code is used internally in the GNU libc. */ +# ifdef __LIBC_INTERNAL_MATH_INLINES +__inline_mathop (__ieee754_sqrt, "fsqrt") +__inline_mathcode2 (__ieee754_atan2, __y, __x, + register long double __value; + __asm __volatile__ ("fpatan\n\t" + : "=t" (__value) + : "0" (__x), "u" (__y) : "st(1)"); + return __value;) +# endif + +#endif /* !__x86_64__ */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/nan.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/nan.h new file mode 100644 index 0000000000..00cb405f18 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/nan.h @@ -0,0 +1,52 @@ +/* `NAN' constant for IEEE 754 machines. + Copyright (C) 1992,1996,1997,1999,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + + +/* IEEE Not A Number. */ + +#if __GNUC_PREREQ(3,3) + +# define NAN (__builtin_nanf ("")) + +#elif defined __GNUC__ + +# define NAN \ + (__extension__ \ + ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; }) \ + { __l: 0x7fc00000UL }).__d) + +#else + +# include + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __nan_bytes { 0x7f, 0xc0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __nan_bytes { 0, 0, 0xc0, 0x7f } +# endif + +static union { unsigned char __c[4]; float __d; } __nan_union + __attribute_used__ = { __nan_bytes }; +# define NAN (__nan_union.__d) + +#endif /* GCC. */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bits/wordsize.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/wordsize.h new file mode 100644 index 0000000000..a40a0d816f --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bits/wordsize.h @@ -0,0 +1,8 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __x86_64__ +# define __WORDSIZE 64 +# define __WORDSIZE_COMPAT32 1 +#else +# define __WORDSIZE 32 +#endif diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/bp-asm.h b/src/system/libroot/posix/glibc/include/arch/x86_64/bp-asm.h new file mode 100644 index 0000000000..ff140ce181 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/bp-asm.h @@ -0,0 +1,141 @@ +/* Bounded-pointer definitions for x86-64 assembler. + Copyright (C) 2001 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _bp_asm_h_ +# define _bp_asm_h_ 1 + +# if __ASSEMBLER__ + +# if __BOUNDED_POINTERS__ + +/* Bounded pointers occupy three words. */ +# define PTR_SIZE 24 +/* Bounded pointer return values are passed back through a hidden + argument that points to caller-allocate space. The hidden arg + occupies one word on the stack. */ +# define RTN_SIZE 6 +/* Although the caller pushes the hidden arg, the callee is + responsible for popping it. */ +# define RET_PTR ret $RTN_SIZE +/* Maintain frame pointer chain in leaf assembler functions for the benefit + of debugging stack traces when bounds violations occur. */ +# define ENTER pushq %rbp; movq %rsp, %rbp +# define LEAVE movq %rbp, %rsp; popq %rbp +/* Stack space overhead of procedure-call linkage: return address and + frame pointer. */ +# define LINKAGE 16 +/* Stack offset of return address after calling ENTER. */ +# define PCOFF 8 + +/* Int 5 is the "bound range" exception also raised by the "bound" + instruction. */ +# define BOUNDS_VIOLATED int $5 + +# define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM) \ + cmpq 8+BP_MEM, VAL_REG; \ + jae 0f; /* continue if value >= low */ \ + BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc) \ + cmpq 16+BP_MEM, VAL_REG; \ + Jcc 0f; /* continue if value < high */ \ + BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM) \ + cmpq 8+BP_MEM, VAL_REG; \ + jb 1f; /* die if value < low */ \ + cmpq 16+BP_MEM, VAL_REG; \ + jb 0f; /* continue if value < high */ \ + 1: BOUNDS_VIOLATED; \ + 0: + +# define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH) \ + CHECK_BOUNDS_LOW(VAL_REG, BP_MEM); \ + addl LENGTH, VAL_REG; \ + cmpq 16+BP_MEM, VAL_REG; \ + jbe 0f; /* continue if value <= high */ \ + BOUNDS_VIOLATED; \ + 0: subq LENGTH, VAL_REG /* restore value */ + +/* Take bounds from BP_MEM and affix them to the pointer + value in %rax, stuffing all into memory at RTN(%esp). + Use %rdx as a scratch register. */ + +# define RETURN_BOUNDED_POINTER(BP_MEM) \ + movq RTN(%rsp), %rdx; \ + movq %rax, 0(%rdx); \ + movq 8+BP_MEM, %rax; \ + movq %rax, 4(%rdx); \ + movq 16+BP_MEM, %rax; \ + movq %rax, 8(%rdx) + +# define RETURN_NULL_BOUNDED_POINTER \ + movl RTN(%rsp), %rdx; \ + movl %rax, 0(%rdx); \ + movl %rax, 4(%rdx); \ + movl %rax, 8(%rdx) + +/* The caller of __errno_location is responsible for allocating space + for the three-word BP return-value and passing pushing its address + as an implicit first argument. */ +# define PUSH_ERRNO_LOCATION_RETURN \ + subl $16, %esp; \ + subl $8, %esp; \ + pushq %rsp + +/* __errno_location is responsible for popping the implicit first + argument, but we must pop the space for the BP itself. We also + dereference the return value in order to dig out the pointer value. */ +# define POP_ERRNO_LOCATION_RETURN \ + popq %rax; \ + addq $16, %rsp + +# else /* !__BOUNDED_POINTERS__ */ + +/* Unbounded pointers occupy one word. */ +# define PTR_SIZE 8 +/* Unbounded pointer return values are passed back in the register %rax. */ +# define RTN_SIZE 0 +/* Use simple return instruction for unbounded pointer values. */ +# define RET_PTR ret +/* Don't maintain frame pointer chain for leaf assembler functions. */ +# define ENTER +# define LEAVE +/* Stack space overhead of procedure-call linkage: return address only. */ +# define LINKAGE 8 +/* Stack offset of return address after calling ENTER. */ +# define PCOFF 0 + +# define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM) +# define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc) +# define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM) +# define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH) +# define RETURN_BOUNDED_POINTER(BP_MEM) + +# define RETURN_NULL_BOUNDED_POINTER + +# define PUSH_ERRNO_LOCATION_RETURN +# define POP_ERRNO_LOCATION_RETURN + +# endif /* !__BOUNDED_POINTERS__ */ + +# endif /* __ASSEMBLER__ */ + +#endif /* _bp_asm_h_ */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/config.h b/src/system/libroot/posix/glibc/include/arch/x86_64/config.h new file mode 100644 index 0000000000..8ac90aa35f --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/config.h @@ -0,0 +1,235 @@ +//#if !defined __ASSEMBLER__ && !defined _ISOMAC && !defined __OPTIMIZE__ +//# error "glibc cannot be compiled without optimization" +//#endif + +/* Another evil option when it comes to compiling the C library is + --ffast-math since it alters the ABI. */ +#if defined __FAST_MATH__ && !defined TEST_FAST_MATH +# error "glibc must not be compiled with -ffast-math" +#endif + +/* Define if using GNU ld, with support for weak symbols in a.out, + and for symbol set and warning messages extensions in a.out and ELF. + This implies HAVE_WEAK_SYMBOLS; set by --with-gnu-ld. */ +#define HAVE_GNU_LD 1 + +/* Define if using ELF, which supports weak symbols. + This implies HAVE_ASM_WEAK_DIRECTIVE and NO_UNDERSCORES; set by + --with-elf. */ +#define HAVE_ELF 1 + +/* Define if using XCOFF. Set by --with-xcoff. */ +#undef HAVE_XCOFF + +/* Define if C symbols are asm symbols. Don't define if C symbols + have a `_' prepended to make the asm symbol. */ +#define NO_UNDERSCORES 1 + +/* Define if weak symbols are available via the `.weak' directive. */ +#define HAVE_ASM_WEAK_DIRECTIVE 1 + +/* Define if weak symbols are available via the `.weakext' directive. */ +#undef HAVE_ASM_WEAKEXT_DIRECTIVE + +/* Define to the assembler line separator character for multiple + assembler instructions per line. Default is `;' */ +#undef ASM_LINE_SEP + +/* Define if not using ELF, but `.init' and `.fini' sections are available. */ +#undef HAVE_INITFINI + +/* Define if __attribute__((section("foo"))) puts quotes around foo. */ +#undef HAVE_SECTION_QUOTES + +/* Define if using the GNU assembler, gas. */ +#define HAVE_GNU_AS 1 + +/* Define if the assembler supports the `.set' directive. */ +#define HAVE_ASM_SET_DIRECTIVE 1 + +/* Define to the name of the assembler's directive for + declaring a symbol global (default `.globl'). */ +#define ASM_GLOBAL_DIRECTIVE .globl + +/* Define to the prefix before `object' or `function' in the + assembler's `.type' directive, if it has one. */ +#undef ASM_TYPE_DIRECTIVE_PREFIX + +/* Define a symbol_name as a global .symbol_name for ld. */ +#undef HAVE_ASM_GLOBAL_DOT_NAME + +/* Define if the assembler generates debugging information directly. */ +#undef HAVE_CPP_ASM_DEBUGINFO + +/* Define if _Unwind_Find_FDE should be exported from glibc. */ +#undef EXPORT_UNWIND_FIND_FDE + +/* Define to use GNU libio instead of GNU stdio. + This is defined by configure under --enable-libio. */ +#define USE_IN_LIBIO 1 + +/* Define if using ELF and the assembler supports the `.previous' + directive. */ +#define HAVE_ASM_PREVIOUS_DIRECTIVE 1 + +/* Define if using ELF and the assembler supports the `.popsection' + directive. */ +#undef HAVE_ASM_POPSECTION_DIRECTIVE + +/* Define if versioning of the library is wanted. */ +#undef DO_VERSIONING + +/* Defined to the oldest ABI we support, like 2.1. */ +#undef GLIBC_OLDEST_ABI + +/* Define if static NSS modules are wanted. */ +#undef DO_STATIC_NSS + +/* Define if gcc uses DWARF2 unwind information for exception support. */ +#define HAVE_DWARF2_UNWIND_INFO 1 + +/* Define if gcc uses DWARF2 unwind information for exception support + with static variable. */ +#define HAVE_DWARF2_UNWIND_INFO_STATIC 1 + +/* Define if the compiler supports __builtin_expect. */ +#define HAVE_BUILTIN_EXPECT 1 + +/* Define if the compiler supports __builtin_memset. */ +#undef HAVE_BUILTIN_MEMSET + +/* Define if the __thread keyword is supported. */ +#undef HAVE___THREAD + +/* Define if the compiler supports __attribute__((tls_model(""))). */ +#undef HAVE_TLS_MODEL_ATTRIBUTE + +/* Define if the regparm attribute shall be used for local functions + (gcc on ix86 only). */ +#undef USE_REGPARMS + +/* Defined on PowerPC if the GCC being used has a problem with clobbering + certain registers (CR0, MQ, CTR, LR) in asm statements. */ +#undef BROKEN_PPC_ASM_CR0 + +/* Defined on SPARC if ld doesn't handle R_SPARC_WDISP22 against .hidden + symbol. sysdeps/sparc/sparc32/elf/configure. */ +#undef BROKEN_SPARC_WDISP22 + +/* Define if the linker supports the -z combreloc option. */ +#undef HAVE_Z_COMBRELOC + +/* Define if the assembler supported .protected. */ +#undef HAVE_PROTECTED + +/* Define if the assembler supported .hidden. */ +#undef HAVE_HIDDEN + +/* Define if the compiler supports __attribute__ ((visibility (...))). */ +#define HAVE_VISIBILITY_ATTRIBUTE 1 + +/* Define if the compiler doesn't support __attribute__ ((visibility (...))) + together with __asm__ redirection properly. */ +#undef HAVE_BROKEN_VISIBILITY_ATTRIBUTE + +/* Define if the compiler doesn't support __attribute__ ((alias (...))) + together with __asm__ redirection properly. */ +#undef HAVE_BROKEN_ALIAS_ATTRIBUTE + +/* Define if _rtld_local structure should be forced into .sdata section. */ +#undef HAVE_SDATA_SECTION + +/* Define if binutils support TLS handling. */ +#undef HAVE_TLS_SUPPORT + +/* Define if the linker supports .preinit_array/.init_array/.fini_array + sections. */ +#undef HAVE_INITFINI_ARRAY + +/* Define if the access to static and hidden variables is position independent + and does not need relocations. */ +#undef PI_STATIC_AND_HIDDEN + +/* Define this to disable the `hidden_proto' et al macros in + include/libc-symbols.h that avoid PLT slots in the shared objects. */ +#undef NO_HIDDEN + + +/* Defined to some form of __attribute__ ((...)) if the compiler supports + a different, more efficient calling convention. */ +#if defined USE_REGPARMS && !defined PROF && !defined __BOUNDED_POINTERS__ +# define internal_function __attribute__ ((regparm (3), stdcall)) +#endif + +/* Linux specific: minimum supported kernel version. */ +#undef __LINUX_KERNEL_VERSION + +/* Override abi-tags ABI version if necessary. */ +#undef __ABI_TAG_VERSION + +/* An extension in gcc 2.96 and up allows the subtraction of two + local labels. */ +#undef HAVE_SUBTRACT_LOCAL_LABELS + +/* bash 2.0 introduced the _XXX_GNU_nonoption_argv_flags_ variable to help + getopt determine whether a parameter is a flag or not. This features + was disabled later since it caused trouble. We are by default therefore + disabling the support as well. */ +#undef USE_NONOPTION_FLAGS + +/* Mach/Hurd specific: define if mig supports the `retcode' keyword. */ +#undef HAVE_MIG_RETCODE + +/* Mach specific: define if the `host_page_size' RPC is available. */ +#undef HAVE_HOST_PAGE_SIZE + +/* Mach/i386 specific: define if the `i386_io_perm_*' RPCs are available. */ +#undef HAVE_I386_IO_PERM_MODIFY + +/* Mach/i386 specific: define if the `i386_set_gdt' RPC is available. */ +#undef HAVE_I386_SET_GDT + +/* + */ + +#ifndef _LIBC + +/* These symbols might be defined by some sysdeps configures. + They are used only in miscellaneous generator programs, not + in compiling libc itself. */ + +/* sysdeps/generic/configure.in */ +#undef HAVE_PSIGNAL + +/* sysdeps/unix/configure.in */ +#define HAVE_STRERROR + +/* sysdeps/unix/common/configure.in */ +#undef HAVE_SYS_SIGLIST +#undef HAVE__SYS_SIGLIST +#undef HAVE__CTYPE_ +#undef HAVE___CTYPE_ +#undef HAVE___CTYPE +#undef HAVE__CTYPE__ +#undef HAVE__CTYPE +#undef HAVE__LOCP + +#endif + +/* + */ + +#ifdef _LIBC + +/* The zic and zdump programs need these definitions. */ + +#define HAVE_STRERROR 1 + +/* The locale code needs these definitions. */ + +#define HAVE_REGEX 1 + +//#define HAVE_MMAP 1 +#undef HAVE_MMAP + +#endif diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/math_ldbl.h b/src/system/libroot/posix/glibc/include/arch/x86_64/math_ldbl.h new file mode 100644 index 0000000000..b9ff8dadaf --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/math_ldbl.h @@ -0,0 +1,79 @@ +#ifndef _MATH_PRIVATE_H_ +#error "Never use directly; include instead." +#endif + +/* A union which permits us to convert between a long double and + three 32 bit ints. */ + +typedef union +{ + long double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + int sign_exponent:16; + unsigned int empty1:16; + unsigned int empty0:32; + } parts; +} ieee_long_double_shape_type; + +/* Get three 32 bit ints from a double. */ + +#define GET_LDOUBLE_WORDS(exp,ix0,ix1,d) \ +do { \ + ieee_long_double_shape_type ew_u; \ + ew_u.value = (d); \ + (exp) = ew_u.parts.sign_exponent; \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define SET_LDOUBLE_WORDS(d,exp,ix0,ix1) \ +do { \ + ieee_long_double_shape_type iw_u; \ + iw_u.parts.sign_exponent = (exp); \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Get the more significant 32 bits of a long double mantissa. */ + +#define GET_LDOUBLE_MSW(v,d) \ +do { \ + ieee_long_double_shape_type sh_u; \ + sh_u.value = (d); \ + (v) = sh_u.parts.msw; \ +} while (0) + +/* Set the more significant 32 bits of a long double mantissa from an int. */ + +#define SET_LDOUBLE_MSW(d,v) \ +do { \ + ieee_long_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Get int from the exponent of a long double. */ + +#define GET_LDOUBLE_EXP(exp,d) \ +do { \ + ieee_long_double_shape_type ge_u; \ + ge_u.value = (d); \ + (exp) = ge_u.parts.sign_exponent; \ +} while (0) + +/* Set exponent of a long double from an int. */ + +#define SET_LDOUBLE_EXP(d,exp) \ +do { \ + ieee_long_double_shape_type se_u; \ + se_u.value = (d); \ + se_u.parts.sign_exponent = (exp); \ + (d) = se_u.value; \ +} while (0) diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/stackinfo.h b/src/system/libroot/posix/glibc/include/arch/x86_64/stackinfo.h new file mode 100644 index 0000000000..60668d10b1 --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86_64 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/src/system/libroot/posix/glibc/include/arch/x86_64/sysdep.h b/src/system/libroot/posix/glibc/include/arch/x86_64/sysdep.h new file mode 100644 index 0000000000..156632493b --- /dev/null +++ b/src/system/libroot/posix/glibc/include/arch/x86_64/sysdep.h @@ -0,0 +1,131 @@ +/* Assembler macros for x86-64. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include_next + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#define cfi_startproc .cfi_startproc +#define cfi_endproc .cfi_endproc +#define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off +#define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg +#define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off +#define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off +#define cfi_offset(reg, off) .cfi_offset reg, off +#define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off +#define cfi_register(r1, r2) .cfi_register r1, r2 +#define cfi_return_column(reg) .cfi_return_column reg +#define cfi_restore(reg) .cfi_restore reg +#define cfi_same_value(reg) .cfi_same_value reg +#define cfi_undefined(reg) .cfi_undefined reg +#define cfi_remember_state .cfi_remember_state +#define cfi_restore_state .cfi_restore_state +#define cfi_window_save .cfi_window_save + +#ifdef HAVE_ELF + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1< Date: Sat, 28 Jul 2012 13:02:34 +0100 Subject: [PATCH 135/273] 64-bit fixes to Hoard. --- src/system/libroot/posix/malloc/arch-specific.cpp | 2 +- src/system/libroot/posix/malloc/superblock.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index 8cb1f6723b..6151fa6407 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -179,7 +179,7 @@ hoardSbrk(long size) if (chunk->size > (size_t)size + sizeof(free_chunk)) { // divide this chunk into smaller bits - uint32 newSize = chunk->size - size; + size_t newSize = chunk->size - size; free_chunk *next = chunk->next; chunk = (free_chunk *)((addr_t)chunk + size); diff --git a/src/system/libroot/posix/malloc/superblock.cpp b/src/system/libroot/posix/malloc/superblock.cpp index 05b6bc4380..5114ad8264 100644 --- a/src/system/libroot/posix/malloc/superblock.cpp +++ b/src/system/libroot/posix/malloc/superblock.cpp @@ -67,7 +67,7 @@ superblock::superblock(int numBlocks, // The number of blocks in the sb. // and insert the block pointers into the linked list. for (int i = 0; i < _numBlocks; i++) { // Make sure the block is on a double-word boundary. - assert(((unsigned int)b & hoardHeap::ALIGNMENT_MASK) == 0); + assert(((unsigned long)b & hoardHeap::ALIGNMENT_MASK) == 0); new(b) block(this); assert(b->getSuperblock() == this); b->setNext(_freeList); From e453c0f4a7d0014d73e9b499aa1fe813dc64c084 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 28 Jul 2012 13:40:09 +0100 Subject: [PATCH 136/273] 64-bit printf warning fixes in libroot. --- src/system/libroot/os/debug.c | 6 +++--- src/system/libroot/posix/malloc/arch-specific.cpp | 5 +++-- src/system/libroot/posix/stdlib/pty.cpp | 4 ++-- src/system/libroot/posix/sys/uname.c | 2 +- src/system/libroot/posix/syslog.cpp | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/system/libroot/os/debug.c b/src/system/libroot/os/debug.c index 7ef95aa28a..a952edc96a 100644 --- a/src/system/libroot/os/debug.c +++ b/src/system/libroot/os/debug.c @@ -60,7 +60,7 @@ bool _rtDebugFlag = true; void debugger(const char *message) { - debug_printf("%ld: DEBUGGER: %s\n", find_thread(NULL), message); + debug_printf("%" B_PRId32 ": DEBUGGER: %s\n", find_thread(NULL), message); _kern_debugger(message); } @@ -261,8 +261,8 @@ _debuggerAssert(const char *file, int line, const char *message) "Assert failed: File: %s, Line: %d, %s", file, line, message); - debug_printf("%ld: ASSERT: %s:%d %s\n", find_thread(NULL), file, line, - buffer); + debug_printf("%" B_PRId32 ": ASSERT: %s:%d %s\n", find_thread(NULL), file, + line, buffer); _kern_debugger(buffer); return 0; diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index 6151fa6407..c9e311c134 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -76,8 +76,9 @@ init_after_fork(void) sHeapArea = area_for((void*)sFreeHeapBase); if (sHeapArea < 0) { // Where is it gone? - debug_printf("hoard: init_after_fork(): thread %ld, Heap area not " - "found! Base address: %p\n", find_thread(NULL), sHeapBase); + debug_printf("hoard: init_after_fork(): thread %" B_PRId32 ", Heap " + "area not found! Base address: %p\n", find_thread(NULL), + sHeapBase); exit(1); } } diff --git a/src/system/libroot/posix/stdlib/pty.cpp b/src/system/libroot/posix/stdlib/pty.cpp index 2da52c50d6..78c43bcb99 100644 --- a/src/system/libroot/posix/stdlib/pty.cpp +++ b/src/system/libroot/posix/stdlib/pty.cpp @@ -37,8 +37,8 @@ ptsname(int masterFD) static char buffer[32]; char letter = 'p'; - snprintf(buffer, sizeof(buffer), "/dev/tt/%c%lx", char(letter + index / 16), - index % 16); + snprintf(buffer, sizeof(buffer), "/dev/tt/%c%" B_PRIx32, + char(letter + index / 16), index % 16); return buffer; } diff --git a/src/system/libroot/posix/sys/uname.c b/src/system/libroot/posix/sys/uname.c index 717f009fd0..8fe5be1d3c 100644 --- a/src/system/libroot/posix/sys/uname.c +++ b/src/system/libroot/posix/sys/uname.c @@ -41,7 +41,7 @@ uname(struct utsname *info) strlcat(info->version, systemInfo.kernel_build_date, sizeof(info->version)); strlcat(info->version, " ", sizeof(info->version)); strlcat(info->version, systemInfo.kernel_build_time, sizeof(info->version)); - snprintf(info->release, sizeof(info->release), "%lld", + snprintf(info->release, sizeof(info->release), "%" B_PRId64, systemInfo.kernel_version); // TODO: make this better diff --git a/src/system/libroot/posix/syslog.cpp b/src/system/libroot/posix/syslog.cpp index 7ed66d97de..97d5b3c08f 100644 --- a/src/system/libroot/posix/syslog.cpp +++ b/src/system/libroot/posix/syslog.cpp @@ -95,7 +95,7 @@ message_to_console(syslog_context *context, const char *text, va_list args) if (context->ident[0]) fprintf(stderr, "'%s' ", context->ident); if (context->options & LOG_PID) - fprintf(stderr, "[%ld] ", find_thread(NULL)); + fprintf(stderr, "[%" B_PRId32 "] ", find_thread(NULL)); vfprintf(stderr, text, args); fputc('\n', stderr); From bd8b78e6eedb24ab48771d18db6e091488cf53d3 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 28 Jul 2012 16:54:30 +0100 Subject: [PATCH 137/273] Added a dumb TLS implementation rather than printing an error. Will properly implement TLS soon, for now a "working" implementation is needed for anything to work properly. --- src/system/libroot/os/arch/x86_64/tls.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/system/libroot/os/arch/x86_64/tls.cpp b/src/system/libroot/os/arch/x86_64/tls.cpp index 794c422090..c45b7f7e59 100644 --- a/src/system/libroot/os/arch/x86_64/tls.cpp +++ b/src/system/libroot/os/arch/x86_64/tls.cpp @@ -18,33 +18,37 @@ #include +static int32 gNextSlot = TLS_FIRST_FREE_SLOT; +static void* gSlots[TLS_MAX_KEYS]; + + int32 tls_allocate(void) { - assert(0 && "tls_allocate: not implemented"); - return 0; + int32 next = atomic_add(&gNextSlot, 1); + if (next >= TLS_MAX_KEYS) + return B_NO_MEMORY; + + return next; } void* tls_get(int32 index) { - assert(0 && "tls_get: not implemented"); - return NULL; + return gSlots[index]; } void** tls_address(int32 index) { - assert(0 && "tls_address: not implemented"); - return NULL; + return &gSlots[index]; } void tls_set(int32 index, void* value) { - assert(0 && "tls_set: not implemented"); + gSlots[index] = value; } - From 12b3e8a8a01e04da03da98410425695880e96347 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 28 Jul 2012 16:57:56 +0100 Subject: [PATCH 138/273] Support x86_64 in the runtime loader. * Added x86_64 linker script and relocation code. * Some 64-bit safety fixes to the heap code. * Added runtime_loader, libroot and bash to the x86_64 image. The boot script will be launched, but will panic shortly after because fork is broken. --- build/jam/Haiku64Image | 8 +- src/system/ldscripts/x86_64/runtime_loader.ld | 53 ++++++++++ src/system/runtime_loader/arch/x86_64/Jamfile | 14 +++ .../arch/x86_64/arch_relocate.cpp | 96 +++++++++++++++++++ src/system/runtime_loader/heap.cpp | 32 +++---- src/system/runtime_loader/images.cpp | 14 ++- 6 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 src/system/ldscripts/x86_64/runtime_loader.ld create mode 100644 src/system/runtime_loader/arch/x86_64/Jamfile create mode 100644 src/system/runtime_loader/arch/x86_64/arch_relocate.cpp diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 1b126d4b37..d887b46abd 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -19,7 +19,7 @@ if $(HAIKU_ATA_STACK) = 1 { IDE_ONLY = "" ; } -SYSTEM_BIN = ; +SYSTEM_BIN = bash ; SYSTEM_APPS = ; @@ -27,7 +27,7 @@ SYSTEM_PREFERENCES = ; SYSTEM_DEMOS = ; -SYSTEM_LIBS = ; +SYSTEM_LIBS = libroot.so ; PRIVATE_SYSTEM_LIBS = ; @@ -74,13 +74,13 @@ AddLibrariesToHaikuHybridImage system lib AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ; # apps -#AddFilesToHaikuImage system : runtime_loader ; +AddFilesToHaikuImage system : runtime_loader ; AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ; AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ; AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ; AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ; -#AddSymlinkToHaikuImage system bin : bash : sh ; +AddSymlinkToHaikuImage system bin : bash : sh ; #AddSymlinkToHaikuImage system bin : less : more ; #AddSymlinkToHaikuImage system bin : gzip : gunzip ; #AddSymlinkToHaikuImage system bin : gzip : zcat ; diff --git a/src/system/ldscripts/x86_64/runtime_loader.ld b/src/system/ldscripts/x86_64/runtime_loader.ld new file mode 100644 index 0000000000..a83a6de457 --- /dev/null +++ b/src/system/ldscripts/x86_64/runtime_loader.ld @@ -0,0 +1,53 @@ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) + +ENTRY(runtime_loader) +SEARCH_DIR("libgcc"); +SECTIONS +{ + . = 0x00200000 + SIZEOF_HEADERS; + + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rela.got : { *(.rela.got) } + .rela.ctors : { *(.rela.ctors) } + .rela.dtors : { *(.rela.dtors) } + .rela.init : { *(.rela.init) } + .rela.fini : { *(.rela.fini) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x90909090 + .plt : { *(.plt) } + + /* text/read-only data */ + .text : { *(.text .text.* .gnu.linkonce.t.*) } =0x90909090 + + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + + /* writable data */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); + __data_start = .; + PROVIDE(_data_start = .); + .data : { *(.data .gnu.linkonce.d.*) } + + __ctor_list = .; + PROVIDE (_ctor_list = .); + .ctors : { *(.ctors) } + PROVIDE (__ctor_end = .); + + + /* uninitialized data (in same segment as writable data) */ + PROVIDE (__bss_start = .); + .bss : { *(.bss) } + + . = ALIGN(0x1000); + PROVIDE (_end = .); + + /* Strip unnecessary stuff */ + /DISCARD/ : { *(.comment .note .eh_frame .dtors) } +} diff --git a/src/system/runtime_loader/arch/x86_64/Jamfile b/src/system/runtime_loader/arch/x86_64/Jamfile new file mode 100644 index 0000000000..a894a0c1b5 --- /dev/null +++ b/src/system/runtime_loader/arch/x86_64/Jamfile @@ -0,0 +1,14 @@ +SubDir HAIKU_TOP src system runtime_loader arch x86_64 ; + +UsePrivateHeaders runtime_loader ; +UsePrivateSystemHeaders ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ; + +StaticLibrary libruntime_loader_$(TARGET_ARCH).a : + arch_relocate.cpp + : + atomic.o + thread.o + arch_string.o +; diff --git a/src/system/runtime_loader/arch/x86_64/arch_relocate.cpp b/src/system/runtime_loader/arch/x86_64/arch_relocate.cpp new file mode 100644 index 0000000000..7148c2e23f --- /dev/null +++ b/src/system/runtime_loader/arch/x86_64/arch_relocate.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include "runtime_loader_private.h" + +#include + +#include +#include +#include + + +static status_t +relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel, + size_t relLength, SymbolLookupCache* cache) +{ + for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) { + int type = ELF64_R_TYPE(rel[i].r_info); + int symIndex = ELF64_R_SYM(rel[i].r_info); + Elf64_Addr symAddr = 0; + + // Resolve the symbol, if any. + if (symIndex != 0) { + Elf64_Sym* sym = SYMBOL(image, symIndex); + + status_t status = resolve_symbol(rootImage, image, sym, cache, + &symAddr); + if (status != B_OK) { + TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n", + SYMNAME(image, sym), status)); + printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n", + SYMNAME(image, sym), status); + return status; + } + } + + // Address of the relocation. + Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset; + + // Calculate the relocation value. + Elf64_Addr relocValue; + switch(type) { + case R_X86_64_NONE: + continue; + case R_X86_64_64: + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + relocValue = symAddr + rel[i].r_addend; + break; + case R_X86_64_PC32: + relocValue = symAddr + rel[i].r_addend - rel[i].r_offset; + break; + case R_X86_64_RELATIVE: + relocValue = image->regions[0].delta + rel[i].r_addend; + break; + default: + TRACE(("unhandled relocation type %d\n", type)); + return B_BAD_DATA; + } + + *(Elf64_Addr *)relocAddr = relocValue; + } + + return B_OK; +} + + +status_t +arch_relocate_image(image_t* rootImage, image_t* image, + SymbolLookupCache* cache) +{ + status_t status; + + // No REL on x86_64. + + // Perform RELA relocations. + if (image->rela) { + status = relocate_rela(rootImage, image, image->rela, image->rela_len, + cache); + if (status != B_OK) + return status; + } + + // PLT relocations (they are RELA on x86_64). + if (image->pltrel) { + status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel, + image->pltrel_len, cache); + if (status != B_OK) + return status; + } + + return B_OK; +} diff --git a/src/system/runtime_loader/heap.cpp b/src/system/runtime_loader/heap.cpp index 03346a978e..02dc286b02 100644 --- a/src/system/runtime_loader/heap.cpp +++ b/src/system/runtime_loader/heap.cpp @@ -35,11 +35,11 @@ static const size_t kInitialHeapSize = 65536; struct free_chunk { - uint32 size; + size_t size; free_chunk *next; - uint32 Size() const; - free_chunk *Split(uint32 splitSize); + size_t Size() const; + free_chunk *Split(size_t splitSize); bool IsTouching(free_chunk *link); free_chunk *Join(free_chunk *link); void Remove(free_chunk *previous = NULL); @@ -50,7 +50,7 @@ struct free_chunk { }; -static uint32 sAvailable; +static size_t sAvailable; static free_chunk sFreeAnchor; @@ -58,10 +58,10 @@ static free_chunk sFreeAnchor; * in this chunk. */ -uint32 +size_t free_chunk::Size() const { - return size - sizeof(uint32); + return size - sizeof(size_t); } @@ -70,13 +70,13 @@ free_chunk::Size() const */ free_chunk * -free_chunk::Split(uint32 splitSize) +free_chunk::Split(size_t splitSize) { - free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(uint32) + splitSize); - chunk->size = size - splitSize - sizeof(uint32); + free_chunk *chunk = (free_chunk *)((uint8 *)this + sizeof(size_t) + splitSize); + chunk->size = size - splitSize - sizeof(size_t); chunk->next = next; - size = splitSize + sizeof(uint32); + size = splitSize + sizeof(size_t); return chunk; } @@ -167,7 +167,7 @@ free_chunk::AllocatedAddress() const free_chunk * free_chunk::SetToAllocated(void *allocated) { - return (free_chunk *)((uint8 *)allocated - sizeof(uint32)); + return (free_chunk *)((uint8 *)allocated - sizeof(size_t)); } @@ -183,7 +183,7 @@ add_area(size_t size) if (area < B_OK) return area; - sAvailable += size - sizeof(uint32); + sAvailable += size - sizeof(size_t); // declare the whole heap as one chunk, and add it // to the free list @@ -198,7 +198,7 @@ add_area(size_t size) static status_t -grow_heap(uint32 bytes) +grow_heap(size_t bytes) { // align the area size to an 32768 bytes boundary bytes = (bytes + 32767) & ~32767; @@ -295,10 +295,10 @@ restart: goto restart; } - if (chunk->Size() > size + sizeof(free_chunk) + 4) { + if (chunk->Size() > size + sizeof(free_chunk) + sizeof(size_t)) { // if this chunk is bigger than the requested size, // we split it to form two chunks (with a minimal - // size of 4 allocatable bytes). + // size of sizeof(size_t) allocatable bytes). free_chunk *freeChunk = chunk->Split(size); last->next = freeChunk; @@ -312,7 +312,7 @@ restart: last->next = chunk->next; } - sAvailable -= size + sizeof(uint32); + sAvailable -= size + sizeof(size_t); return chunk->AllocatedAddress(); } diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp index 0f504a9335..6c6c460285 100644 --- a/src/system/runtime_loader/images.cpp +++ b/src/system/runtime_loader/images.cpp @@ -23,8 +23,16 @@ #include "runtime_loader_private.h" -#define RLD_PROGRAM_BASE 0x00200000 - /* keep in sync with app ldscript */ +// keep in sync with app ldscript +#ifdef __x86_64__ + // runtime_loader potentially occupies 0x200000 - 0x600000 due to large + // page segment alignment. +# define RLD_PROGRAM_BASE 0x600000 +# define MAX_PAGE_SIZE 0x200000 +#else +# define RLD_PROGRAM_BASE 0x200000 +# define MAX_PAGE_SIZE B_PAGE_SIZE +#endif bool gInvalidImageIDs; @@ -319,7 +327,7 @@ map_image(int fd, char const* path, image_t* image, bool fixed) // Check whether the segments have an unreasonable amount of unused space // inbetween. - if (reservedSize > length + 8 * 1024) + if (reservedSize > length + MAX_PAGE_SIZE * 2) return B_BAD_DATA; // reserve that space and allocate the areas from that one From 6e2f6d1ace7490a200dcff70c52acf2af59c5bc3 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 29 Jul 2012 09:31:14 +0100 Subject: [PATCH 139/273] Changed cookie type for get_next_area_info() to ssize_t. The cookie is used to store the base address of the area that was just visited. On 64-bit systems, int32 is not sufficient. Therefore, changed to ssize_t which retains compatibility on x86 while expanding to a sufficient size on x86_64. --- headers/os/kernel/OS.h | 2 +- headers/private/kernel/vm/vm.h | 2 +- headers/private/system/syscalls.h | 2 +- src/apps/processcontroller/MemoryBarMenuItem.cpp | 2 +- src/bin/listarea.c | 2 +- src/kits/debug/SymbolLookup.cpp | 2 +- src/servers/debug/DebugServer.cpp | 2 +- src/system/kernel/team.cpp | 12 +++++++----- src/system/kernel/vm/vm.cpp | 13 ++++++------- src/system/libroot/os/area.c | 2 +- 10 files changed, 21 insertions(+), 20 deletions(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 633e4541b5..6fc6a3badd 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -96,7 +96,7 @@ extern status_t set_area_protection(area_id id, uint32 newProtection); /* system private, use macros instead */ extern status_t _get_area_info(area_id id, area_info *areaInfo, size_t size); -extern status_t _get_next_area_info(team_id team, int32 *cookie, +extern status_t _get_next_area_info(team_id team, ssize_t *cookie, area_info *areaInfo, size_t size); #define get_area_info(id, areaInfo) \ diff --git a/headers/private/kernel/vm/vm.h b/headers/private/kernel/vm/vm.h index 9163e3bca1..ef1b829915 100644 --- a/headers/private/kernel/vm/vm.h +++ b/headers/private/kernel/vm/vm.h @@ -176,7 +176,7 @@ status_t _user_get_memory_properties(team_id teamID, const void *address, area_id _user_area_for(void *address); area_id _user_find_area(const char *name); status_t _user_get_area_info(area_id area, area_info *info); -status_t _user_get_next_area_info(team_id team, int32 *cookie, area_info *info); +status_t _user_get_next_area_info(team_id team, ssize_t *cookie, area_info *info); status_t _user_resize_area(area_id area, size_t newSize); area_id _user_transfer_area(area_id area, void **_address, uint32 addressSpec, team_id target); diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index b104bb6cf8..0e588b2cd3 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -411,7 +411,7 @@ extern status_t _kern_delete_area(area_id area); extern area_id _kern_area_for(void *address); extern area_id _kern_find_area(const char *name); extern status_t _kern_get_area_info(area_id area, area_info *info); -extern status_t _kern_get_next_area_info(team_id team, int32 *cookie, +extern status_t _kern_get_next_area_info(team_id team, ssize_t *cookie, area_info *info); extern status_t _kern_resize_area(area_id area, size_t newSize); extern area_id _kern_transfer_area(area_id area, void **_address, diff --git a/src/apps/processcontroller/MemoryBarMenuItem.cpp b/src/apps/processcontroller/MemoryBarMenuItem.cpp index c51cd750be..34fca14177 100644 --- a/src/apps/processcontroller/MemoryBarMenuItem.cpp +++ b/src/apps/processcontroller/MemoryBarMenuItem.cpp @@ -246,7 +246,7 @@ void MemoryBarMenuItem::BarUpdate() { area_info areaInfo; - int32 cookie = 0; + ssize_t cookie = 0; int64 lram_size = 0; int64 lwram_size = 0; bool exists = false; diff --git a/src/bin/listarea.c b/src/bin/listarea.c index 00ab99bfd5..f381bb16ee 100644 --- a/src/bin/listarea.c +++ b/src/bin/listarea.c @@ -41,7 +41,7 @@ show_memory_totals(void) static void list_areas_for_id(team_id id) { - int32 cookie = 0; + ssize_t cookie = 0; team_info teamInfo; area_info areaInfo; diff --git a/src/kits/debug/SymbolLookup.cpp b/src/kits/debug/SymbolLookup.cpp index 930ac95a9f..d29f4e8f1b 100644 --- a/src/kits/debug/SymbolLookup.cpp +++ b/src/kits/debug/SymbolLookup.cpp @@ -86,7 +86,7 @@ RemoteMemoryAccessor::Init() // get a list of the team's areas area_info areaInfo; - int32 cookie = 0; + ssize_t cookie = 0; status_t error; while ((error = get_next_area_info(fTeam, &cookie, &areaInfo)) == B_OK) { TRACE(("area %ld: address: %p, size: %ld, name: %s\n", areaInfo.area, diff --git a/src/servers/debug/DebugServer.cpp b/src/servers/debug/DebugServer.cpp index 83e49709c5..8abb4c7a64 100644 --- a/src/servers/debug/DebugServer.cpp +++ b/src/servers/debug/DebugServer.cpp @@ -734,7 +734,7 @@ TeamDebugHandler::_LookupSymbolAddress( // lookup failed: find area containing the IP bool useAreaInfo = false; area_info info; - int32 cookie = 0; + ssize_t cookie = 0; while (get_next_area_info(fTeam, &cookie, &info) == B_OK) { if ((addr_t)info.address <= (addr_t)address && (addr_t)info.address + info.size > (addr_t)address) { diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index acdc915f26..b8fbde285e 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -1942,7 +1942,8 @@ fork_team(void) struct area_info info; thread_id threadID; status_t status; - int32 cookie; + ssize_t areaCookie; + int32 imageCookie; TRACE(("fork_team(): team %" B_PRId32 "\n", parentTeam->id)); @@ -2030,8 +2031,8 @@ fork_team(void) // TODO: should be able to handle stack areas differently (ie. don't have // them copy-on-write) - cookie = 0; - while (get_next_area_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { + areaCookie = 0; + while (get_next_area_info(B_CURRENT_TEAM, &areaCookie, &info) == B_OK) { if (info.area == parentTeam->user_data_area) { // don't clone the user area; just create a new one status = create_team_user_data(team); @@ -2077,8 +2078,9 @@ fork_team(void) // copy image list image_info imageInfo; - cookie = 0; - while (get_next_image_info(parentTeam->id, &cookie, &imageInfo) == B_OK) { + imageCookie = 0; + while (get_next_image_info(parentTeam->id, &imageCookie, &imageInfo) + == B_OK) { image_id image = register_image(team, &imageInfo, sizeof(imageInfo)); if (image < 0) goto err5; diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 5d5f936459..7aaafabcdc 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -5750,7 +5750,7 @@ _get_area_info(area_id id, area_info* info, size_t size) status_t -_get_next_area_info(team_id team, int32* cookie, area_info* info, size_t size) +_get_next_area_info(team_id team, ssize_t* cookie, area_info* info, size_t size) { addr_t nextBase = *(addr_t*)cookie; @@ -5779,8 +5779,7 @@ _get_next_area_info(team_id team, int32* cookie, area_info* info, size_t size) } fill_area_info(area, info, size); - *cookie = (int32)(area->Base()); - // TODO: Not 64 bit safe! + *cookie = (ssize_t)(area->Base()); return B_OK; } @@ -5987,13 +5986,13 @@ _user_get_area_info(area_id area, area_info* userInfo) status_t -_user_get_next_area_info(team_id team, int32* userCookie, area_info* userInfo) +_user_get_next_area_info(team_id team, ssize_t* userCookie, area_info* userInfo) { - int32 cookie; + ssize_t cookie; if (!IS_USER_ADDRESS(userCookie) || !IS_USER_ADDRESS(userInfo) - || user_memcpy(&cookie, userCookie, sizeof(int32)) < B_OK) + || user_memcpy(&cookie, userCookie, sizeof(ssize_t)) < B_OK) return B_BAD_ADDRESS; area_info info; @@ -6004,7 +6003,7 @@ _user_get_next_area_info(team_id team, int32* userCookie, area_info* userInfo) //info.protection &= B_USER_PROTECTION; - if (user_memcpy(userCookie, &cookie, sizeof(int32)) < B_OK + if (user_memcpy(userCookie, &cookie, sizeof(ssize_t)) < B_OK || user_memcpy(userInfo, &info, sizeof(area_info)) < B_OK) return B_BAD_ADDRESS; diff --git a/src/system/libroot/os/area.c b/src/system/libroot/os/area.c index bb28838a91..0fedf2fc48 100644 --- a/src/system/libroot/os/area.c +++ b/src/system/libroot/os/area.c @@ -70,7 +70,7 @@ _get_area_info(area_id id, area_info *areaInfo, size_t size) status_t -_get_next_area_info(team_id team, int32 *cookie, area_info *areaInfo, size_t size) +_get_next_area_info(team_id team, ssize_t *cookie, area_info *areaInfo, size_t size) { // size is not yet used, but may, if area_info changes (void)size; From 03add8e7c216a9ba83a2c565cb82962d6cdc53c4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 29 Jul 2012 11:39:01 +0100 Subject: [PATCH 140/273] Implemented TLS for x86_64. --- src/system/boot/platform/bios_ia32/long_asm.S | 1 + src/system/kernel/arch/x86/32/thread.cpp | 23 ------------- src/system/kernel/arch/x86/64/thread.cpp | 16 ++------- src/system/kernel/arch/x86/arch_thread.cpp | 24 ++++++++++++++ src/system/libroot/os/arch/x86_64/thread.cpp | 8 +++-- src/system/libroot/os/arch/x86_64/tls.cpp | 33 ++++++++++++------- 6 files changed, 55 insertions(+), 50 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 8c07f391ec..72b30c26cf 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -65,6 +65,7 @@ FUNCTION(long_enter_kernel): // Set data segments. mov $KERNEL_DATA_SEG, %ax mov %ax, %ss + xor %ax, %ax mov %ax, %ds mov %ax, %es mov %ax, %fs diff --git a/src/system/kernel/arch/x86/32/thread.cpp b/src/system/kernel/arch/x86/32/thread.cpp index 4df16852d7..71b484c370 100644 --- a/src/system/kernel/arch/x86/32/thread.cpp +++ b/src/system/kernel/arch/x86/32/thread.cpp @@ -172,29 +172,6 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, } -/*! Initializes the user-space TLS local storage pointer in - the thread structure, and the reserved TLS slots. - - Is called from _create_user_thread_kentry(). -*/ -status_t -arch_thread_init_tls(Thread *thread) -{ - uint32 tls[TLS_USER_THREAD_SLOT + 1]; - - thread->user_local_storage = thread->user_stack_base - + thread->user_stack_size; - - // initialize default TLS fields - memset(tls, 0, sizeof(tls)); - tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; - tls[TLS_THREAD_ID_SLOT] = thread->id; - tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; - - return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls)); -} - - void arch_thread_dump_info(void *info) { diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 1d0434fde0..51f4676e82 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -52,7 +52,8 @@ x86_restart_syscall(iframe* frame) void x86_set_tls_context(Thread* thread) { - + // Set FS segment base address to the TLS segment. + x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); } @@ -127,19 +128,6 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, } -/*! Initializes the user-space TLS local storage pointer in - the thread structure, and the reserved TLS slots. - - Is called from _create_user_thread_kentry(). -*/ -status_t -arch_thread_init_tls(Thread* thread) -{ - dprintf("arch_thread_init_tls: TODO\n"); - return B_OK; -} - - void arch_thread_dump_info(void* info) { diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index 401f9d42dc..8b17b1d015 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -198,6 +199,29 @@ arch_team_init_team_struct(Team* p, bool kernel) } +/*! Initializes the user-space TLS local storage pointer in + the thread structure, and the reserved TLS slots. + + Is called from _create_user_thread_kentry(). +*/ +status_t +arch_thread_init_tls(Thread* thread) +{ + size_t tls[TLS_USER_THREAD_SLOT + 1]; + + thread->user_local_storage = thread->user_stack_base + + thread->user_stack_size; + + // initialize default TLS fields + memset(tls, 0, sizeof(tls)); + tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; + tls[TLS_THREAD_ID_SLOT] = thread->id; + tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; + + return user_memcpy((void*)thread->user_local_storage, tls, sizeof(tls)); +} + + void arch_thread_context_switch(Thread* from, Thread* to) { diff --git a/src/system/libroot/os/arch/x86_64/thread.cpp b/src/system/libroot/os/arch/x86_64/thread.cpp index 7b12f02e39..10614ba6c6 100644 --- a/src/system/libroot/os/arch/x86_64/thread.cpp +++ b/src/system/libroot/os/arch/x86_64/thread.cpp @@ -11,8 +11,12 @@ thread_id find_thread(const char* name) { - // TODO x86_64: x86 is doing some TLS thing here. Should that be done here - // too? + if (!name) { + thread_id thread; + __asm__ __volatile__ ("movq %%fs:8, %%rax" : "=a" (thread)); + return thread; + } + return _kern_find_thread(name); } diff --git a/src/system/libroot/os/arch/x86_64/tls.cpp b/src/system/libroot/os/arch/x86_64/tls.cpp index c45b7f7e59..733dc7b2e3 100644 --- a/src/system/libroot/os/arch/x86_64/tls.cpp +++ b/src/system/libroot/os/arch/x86_64/tls.cpp @@ -4,10 +4,6 @@ */ -// TODO x86_64. -// Also want to add inline versions to support/TLS.h. - - #ifndef _NO_INLINE_ASM # define _NO_INLINE_ASM 1 #endif @@ -19,7 +15,6 @@ static int32 gNextSlot = TLS_FIRST_FREE_SLOT; -static void* gSlots[TLS_MAX_KEYS]; int32 @@ -34,21 +29,37 @@ tls_allocate(void) void* -tls_get(int32 index) +tls_get(int32 _index) { - return gSlots[index]; + int64 index = _index; + void* ret; + + __asm__ __volatile__ ( + "movq %%fs:(, %%rdi, 8), %%rax" + : "=a" (ret) : "D" (index)); + return ret; } void** -tls_address(int32 index) +tls_address(int32 _index) { - return &gSlots[index]; + int64 index = _index; + void** ret; + + __asm__ __volatile__ ( + "movq %%fs:0, %%rax\n\t" + "leaq (%%rax, %%rdi, 8), %%rax\n\t" + : "=a" (ret) : "D" (index)); + return ret; } void -tls_set(int32 index, void* value) +tls_set(int32 _index, void* value) { - gSlots[index] = value; + int64 index = _index; + __asm__ __volatile__ ( + "movq %%rsi, %%fs:(, %%rdi, 8)" + : : "D" (index), "S" (value)); } From afde37ff9b417de6e7e4b348a4df556c4d25de6f Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 29 Jul 2012 14:31:11 +0100 Subject: [PATCH 141/273] Prevent allocating address 0 when inserting an area with B_ANY_ADDRESS. The USER_BASE_ANY definition exists to specify where to start searching for B_ANY_ADDRESS allocations, but this was not being used correctly. On x86_64, this was causing the runtime loader's heap to be allocated at address 0 so NULL pointer accesses were not getting caught. --- src/system/kernel/vm/VMUserAddressSpace.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/system/kernel/vm/VMUserAddressSpace.cpp b/src/system/kernel/vm/VMUserAddressSpace.cpp index 1420e447e5..32730a41cb 100644 --- a/src/system/kernel/vm/VMUserAddressSpace.cpp +++ b/src/system/kernel/vm/VMUserAddressSpace.cpp @@ -461,8 +461,8 @@ VMUserAddressSpace::_InsertAreaSlot(addr_t start, addr_t size, addr_t end, bool foundSpot = false; TRACE(("VMUserAddressSpace::_InsertAreaSlot: address space %p, start " - "0x%lx, size %ld, end 0x%lx, addressSpec %ld, area %p\n", this, start, - size, end, addressSpec, area)); + "0x%lx, size %ld, end 0x%lx, addressSpec %" B_PRIu32 ", area %p\n", + this, start, size, end, addressSpec, area)); // do some sanity checking if (start < fBase || size == 0 || end > fEndAddress @@ -514,8 +514,8 @@ second_chance: // find a hole big enough for a new area if (last == NULL) { // see if we can build it at the beginning of the virtual map - addr_t alignedBase = ROUNDUP(fBase, alignment); - if (is_valid_spot(fBase, alignedBase, size, + addr_t alignedBase = ROUNDUP(start, alignment); + if (is_valid_spot(start, alignedBase, size, next == NULL ? end : next->Base())) { foundSpot = true; area->SetBase(alignedBase); From bd16f0dd82af89e53cb3f616a0bbc2d448b5266a Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 08:25:16 +0100 Subject: [PATCH 142/273] Fixed configure for legacy buildtools. The elfedit tool doesn't exist with the old binutils, so configure was failing when it tried to get the path to it. Only try to search for it if building GCC 4. --- configure | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 9b0f8cd76a..a80eed5eff 100755 --- a/configure +++ b/configure @@ -511,7 +511,11 @@ if [ -n "$crossToolsPrefix" ]; then get_build_tool_path LD ld get_build_tool_path OBJCOPY objcopy get_build_tool_path RANLIB ranlib - get_build_tool_path ELFEDIT elfedit + case $HAIKU_GCC_RAW_VERSION in + 4.*) + get_build_tool_path ELFEDIT elfedit + ;; + esac fi # prepare gcc settings From 5568c5055cdb40225d2521f4dde75eb256e368d3 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 08:59:19 +0100 Subject: [PATCH 143/273] Added coreutils to the x86_64 image. --- build/jam/Haiku64Image | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index d887b46abd..18bb09cdcb 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -19,7 +19,14 @@ if $(HAIKU_ATA_STACK) = 1 { IDE_ONLY = "" ; } -SYSTEM_BIN = bash ; +SYSTEM_BIN = "[" base64 basename bash cat chgrp chmod chown chroot cksum comm + cp split cut date dd dircolors dirname du echo env expand expr factor false + fmt fold getlimits groups head hostname id install join kill link + link ln logname ls md5sum mkdir mkfifo mktemp mv nl nohup nproc od paste + pathchk pr printenv printf ptx pwd readlink rm rmdir safemode seq sha1sum + shred shuf sleep sort split stat stty su sum sync tac tail tee test timeout + touch tr true truncate tsort tty unexpand uname uniq unlink wc whoami yes +; SYSTEM_APPS = ; From c0d28c01990d8815dddc645177f44b9ce361d186 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 13:52:51 +0100 Subject: [PATCH 144/273] Implemented signals for x86_64. --- headers/posix/arch/x86_64/signal.h | 125 ++++++++++++---- headers/private/kernel/arch/x86/arch_thread.h | 2 - .../system/arch/x86_64/arch_commpage_defs.h | 4 +- src/system/kernel/arch/x86/32/thread.cpp | 20 ++- src/system/kernel/arch/x86/64/interrupts.S | 9 +- src/system/kernel/arch/x86/64/signals.cpp | 17 ++- src/system/kernel/arch/x86/64/signals_asm.S | 56 ++++++++ src/system/kernel/arch/x86/64/thread.cpp | 136 +++++++++++++++++- src/system/kernel/arch/x86/Jamfile | 1 + src/system/kernel/arch/x86/arch_thread.cpp | 17 --- src/system/kernel/arch/x86/asm_offsets.cpp | 1 + src/system/kernel/arch/x86/x86_signals.h | 2 + 12 files changed, 331 insertions(+), 59 deletions(-) create mode 100644 src/system/kernel/arch/x86/64/signals_asm.S diff --git a/headers/posix/arch/x86_64/signal.h b/headers/posix/arch/x86_64/signal.h index f48a72f5fa..871d1f59b6 100644 --- a/headers/posix/arch/x86_64/signal.h +++ b/headers/posix/arch/x86_64/signal.h @@ -12,35 +12,108 @@ #if __x86_64__ -struct vregs { - unsigned long rax; /* gp regs */ - unsigned long rdx; - unsigned long rcx; - unsigned long rbx; - unsigned long rsi; - unsigned long rdi; - unsigned long rbp; - unsigned long rsp; - - unsigned long r8; /* egp regs */ - unsigned long r9; - unsigned long r10; - unsigned long r11; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; - - unsigned long rip; - -/*TODO: add -* Floatpoint -* MMX -* SSE -*/ +struct fp_stack { + unsigned char st0[10]; + unsigned char _reserved_42_47[6]; + unsigned char st1[10]; + unsigned char _reserved_58_63[6]; + unsigned char st2[10]; + unsigned char _reserved_74_79[6]; + unsigned char st3[10]; + unsigned char _reserved_90_95[6]; + unsigned char st4[10]; + unsigned char _reserved_106_111[6]; + unsigned char st5[10]; + unsigned char _reserved_122_127[6]; + unsigned char st6[10]; + unsigned char _reserved_138_143[6]; + unsigned char st7[10]; + unsigned char _reserved_154_159[6]; }; +struct mmx_regs { + unsigned char mm0[10]; + unsigned char _reserved_42_47[6]; + unsigned char mm1[10]; + unsigned char _reserved_58_63[6]; + unsigned char mm2[10]; + unsigned char _reserved_74_79[6]; + unsigned char mm3[10]; + unsigned char _reserved_90_95[6]; + unsigned char mm4[10]; + unsigned char _reserved_106_111[6]; + unsigned char mm5[10]; + unsigned char _reserved_122_127[6]; + unsigned char mm6[10]; + unsigned char _reserved_138_143[6]; + unsigned char mm7[10]; + unsigned char _reserved_154_159[6]; +}; + +struct xmm_regs { + unsigned char xmm0[16]; + unsigned char xmm1[16]; + unsigned char xmm2[16]; + unsigned char xmm3[16]; + unsigned char xmm4[16]; + unsigned char xmm5[16]; + unsigned char xmm6[16]; + unsigned char xmm7[16]; + unsigned char xmm8[16]; + unsigned char xmm9[16]; + unsigned char xmm10[16]; + unsigned char xmm11[16]; + unsigned char xmm12[16]; + unsigned char xmm13[16]; + unsigned char xmm14[16]; + unsigned char xmm15[16]; +}; + +struct fpu_state { + unsigned short control; + unsigned short status; + unsigned short tag; + unsigned short opcode; + unsigned long rip; + unsigned long rdp; + unsigned int mxcsr; + unsigned int mscsr_mask; + + union { + struct fp_stack fp; + struct mmx_regs mmx; + }; + + struct xmm_regs xmm; + unsigned char _reserved_416_511[96]; +}; + +struct vregs { + unsigned long rax; + unsigned long rbx; + unsigned long rcx; + unsigned long rdx; + unsigned long rdi; + unsigned long rsi; + unsigned long rbp; + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + + unsigned long rsp; + unsigned long rip; + unsigned long rflags; + + struct fpu_state fpu; +}; + + #endif /* __x86_64__ */ #endif /* _ARCH_SIGNAL_H_ */ diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 850cfc9973..0769195543 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -25,8 +25,6 @@ struct iframe* x86_get_thread_user_iframe(Thread* thread); phys_addr_t x86_next_page_directory(Thread* from, Thread* to); void x86_initial_return_to_userland(Thread* thread, struct iframe* iframe); -uint8* x86_get_signal_stack(Thread* thread, struct iframe* frame, - struct sigaction* action); void x86_restart_syscall(struct iframe* frame); void x86_set_tls_context(Thread* thread); diff --git a/headers/private/system/arch/x86_64/arch_commpage_defs.h b/headers/private/system/arch/x86_64/arch_commpage_defs.h index f298a32678..bf7809e38a 100644 --- a/headers/private/system/arch/x86_64/arch_commpage_defs.h +++ b/headers/private/system/arch/x86_64/arch_commpage_defs.h @@ -11,7 +11,9 @@ #define COMMPAGE_ENTRY_X86_MEMCPY (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0) #define COMMPAGE_ENTRY_X86_MEMSET (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 1) +#define COMMPAGE_ENTRY_X86_SIGNAL_HANDLER \ + (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 2) -#define ARCH_USER_COMMPAGE_ADDR (0xffffffffffff0000) +#define ARCH_USER_COMMPAGE_ADDR (0xffffffffffff0000) #endif /* _SYSTEM_ARCH_x86_64_COMMPAGE_DEFS_H */ diff --git a/src/system/kernel/arch/x86/32/thread.cpp b/src/system/kernel/arch/x86/32/thread.cpp index 71b484c370..c4eaf9737a 100644 --- a/src/system/kernel/arch/x86/32/thread.cpp +++ b/src/system/kernel/arch/x86/32/thread.cpp @@ -107,6 +107,22 @@ x86_set_tls_context(Thread *thread) } +static uint8* +get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action) +{ + // use the alternate signal stack if we should and can + if (thread->signal_stack_enabled + && (action->sa_flags & SA_ONSTACK) != 0 + && (frame->user_sp < thread->signal_stack_base + || frame->user_sp >= thread->signal_stack_base + + thread->signal_stack_size)) { + return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); + } + + return (uint8*)frame->user_sp; +} + + // #pragma mark - @@ -290,7 +306,7 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action, signalFrameData->context.uc_mcontext.ebx = frame->bx; x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); - // fill in signalFrameData->context.uc_stack + // Fill in signalFrameData->context.uc_stack signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); // store orig_eax/orig_edx in syscall_restart_return_value @@ -299,7 +315,7 @@ arch_setup_signal_frame(Thread* thread, struct sigaction* action, // get the stack to use -- that's either the current one or a special signal // stack - uint8* userStack = x86_get_signal_stack(thread, frame, action); + uint8* userStack = get_signal_stack(thread, frame, action); // copy the signal frame data onto the stack userStack -= sizeof(*signalFrameData); diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index 3f2d621ea9..acc82a083b 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -337,8 +337,9 @@ FUNCTION(x86_64_syscall_entry): // Get the system call table entry. Note I'm hardcoding the shift because // sizeof(syscall_info) is 16 and scale factors of 16 aren't supported, // so can't just do leaq kSyscallInfos(, %rax, SYSCALL_INFO_sizeof). - shlq $4, %r14 - leaq kSyscallInfos(, %r14, 1), %rax + movq %r14, %rax + shlq $4, %rax + leaq kSyscallInfos(, %rax, 1), %rax // Check the number of call arguments, greater than 6 (6 * 8 = 48) requires // a stack copy. @@ -388,6 +389,10 @@ FUNCTION(x86_64_syscall_entry): UPDATE_THREAD_KERNEL_TIME() + // If we've just restored a signal frame, use the IRET path. + cmpq $SYSCALL_RESTORE_SIGNAL_FRAME, %r14 + je .Liret + // If the return address is not canonical, return using the IRET path. // On Intel's implementation of SYSRET, the canonical address check for the // return address is performed before the switch to user mode, so a fault diff --git a/src/system/kernel/arch/x86/64/signals.cpp b/src/system/kernel/arch/x86/64/signals.cpp index 0b07851096..b8a29f1a39 100644 --- a/src/system/kernel/arch/x86/64/signals.cpp +++ b/src/system/kernel/arch/x86/64/signals.cpp @@ -15,12 +15,25 @@ #include #include -#include "syscall_numbers.h" + +extern "C" void _user_signal_handler(void); +extern int _user_signal_handler_end; void x86_initialize_commpage_signal_handler() { - // TODO x86_64 + void* handlerCode = (void*)&_user_signal_handler; + void* handlerCodeEnd = &_user_signal_handler_end; + + // Copy the signal handler code to the commpage. + size_t len = (size_t)((addr_t)handlerCodeEnd - (addr_t)handlerCode); + fill_commpage_entry(COMMPAGE_ENTRY_X86_SIGNAL_HANDLER, handlerCode, len); + + // Add symbol to the commpage image. + image_id image = get_commpage_image(); + elf_add_memory_image_symbol(image, "commpage_signal_handler", + ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER], + len, B_SYMBOL_TYPE_TEXT); } diff --git a/src/system/kernel/arch/x86/64/signals_asm.S b/src/system/kernel/arch/x86/64/signals_asm.S new file mode 100644 index 0000000000..078a4c16af --- /dev/null +++ b/src/system/kernel/arch/x86/64/signals_asm.S @@ -0,0 +1,56 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include "asm_offsets.h" +#include "syscall_numbers.h" + + +.text + + +// Userspace signal handler wrapper, copied to the commpage. +FUNCTION(_user_signal_handler): + push %rbp + movq %rsp, %rbp + + // RDI points to the signal_frame_data structure, however we'll overwrite + // that with the function arguments, so move it somewhere else. We can use + // callee-save registers here without preserving them because the old value + // will be restored when the frame is restored. + movq %rdi, %r12 + + // Check the handler type. + cmpb $0, SIGNAL_FRAME_DATA_siginfo_handler(%r12) + jne .Lsiginfo_handler + +.Lsimple_handler: + // Fetch other arguments (user data, vregs). + movq SIGNAL_FRAME_DATA_user_data(%r12), %rsi + leaq SIGNAL_FRAME_DATA_context + UCONTEXT_T_uc_mcontext(%r12), %rdx + +.Lcall_handler: + // Get the handler address and the signal number first argument. + movq SIGNAL_FRAME_DATA_handler(%r12), %rax + movl SIGNAL_FRAME_DATA_info + SIGINFO_T_si_signo(%r12), %edi + + // Call the handler. + callq *%rax + + // Perform the restore_signal_frame() syscall, should not return. + movq $SYSCALL_RESTORE_SIGNAL_FRAME, %rax + movq %r12, %rdi + syscall + +.Lsiginfo_handler: + // Fetch other arguments (info pointer, context, user data). + leaq SIGNAL_FRAME_DATA_info(%r12), %rsi + leaq SIGNAL_FRAME_DATA_context(%r12), %rdx + movq SIGNAL_FRAME_DATA_user_data(%r12), %rcx + jmp .Lcall_handler +FUNCTION_END(_user_signal_handler) +SYMBOL(_user_signal_handler_end): diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 51f4676e82..79434ac458 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -12,7 +12,7 @@ #include -#include +#include #include #include #include @@ -57,6 +57,26 @@ x86_set_tls_context(Thread* thread) } +static uint8* +get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action) +{ + // Use the alternate signal stack if we should and can. + if (thread->signal_stack_enabled + && (action->sa_flags & SA_ONSTACK) != 0 + && (frame->user_sp < thread->signal_stack_base + || frame->user_sp >= thread->signal_stack_base + + thread->signal_stack_size)) { + return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); + } + + // We are going to use the stack that we are already on. We must not touch + // the red zone (128 byte area below the stack pointer, reserved for use + // by functions to store temporary data and guaranteed not to be modified + // by signal handlers). + return (uint8*)(frame->user_sp - 128); +} + + // #pragma mark - @@ -203,8 +223,8 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, filled in: - \c context.uc_stack: The stack currently used by the thread. - \c context.uc_mcontext: The current userland state of the registers. - - \c syscall_restart_return_value: Architecture specific use. On x86 the - value of eax and edx which are overwritten by the syscall return value. + - \c syscall_restart_return_value: Architecture specific use. On x86_64 the + value of rax which is overwritten by the syscall return value. Furthermore the function needs to set \c thread->user_signal_context to the userland pointer to the \c ucontext_t on the user stack. @@ -219,14 +239,116 @@ status_t arch_setup_signal_frame(Thread* thread, struct sigaction* action, struct signal_frame_data* signalFrameData) { - panic("arch_setup_signal_frame: TODO\n"); - return B_ERROR; + iframe* frame = x86_get_current_iframe(); + if (!IFRAME_IS_USER(frame)) { + panic("arch_setup_signal_frame(): No user iframe!"); + return B_BAD_VALUE; + } + + // Store the register state. + signalFrameData->context.uc_mcontext.rax = frame->ax; + signalFrameData->context.uc_mcontext.rbx = frame->bx; + signalFrameData->context.uc_mcontext.rcx = frame->cx; + signalFrameData->context.uc_mcontext.rdx = frame->dx; + signalFrameData->context.uc_mcontext.rdi = frame->di; + signalFrameData->context.uc_mcontext.rsi = frame->si; + signalFrameData->context.uc_mcontext.rbp = frame->bp; + signalFrameData->context.uc_mcontext.r8 = frame->r8; + signalFrameData->context.uc_mcontext.r9 = frame->r9; + signalFrameData->context.uc_mcontext.r10 = frame->r10; + signalFrameData->context.uc_mcontext.r11 = frame->r11; + signalFrameData->context.uc_mcontext.r12 = frame->r12; + signalFrameData->context.uc_mcontext.r13 = frame->r13; + signalFrameData->context.uc_mcontext.r14 = frame->r14; + signalFrameData->context.uc_mcontext.r15 = frame->r15; + signalFrameData->context.uc_mcontext.rsp = frame->user_sp; + signalFrameData->context.uc_mcontext.rip = frame->ip; + signalFrameData->context.uc_mcontext.rflags = frame->flags; + + // Store the FPU state. There appears to be a bug in GCC where the aligned + // attribute on a structure is being ignored when the structure is allocated + // on the stack, so even if the fpu_state struct has aligned(16) it may not + // get aligned correctly. Instead, use the current thread's FPU save area + // and then memcpy() to the frame structure. + x86_fxsave(thread->arch_info.fpu_state); + memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, + thread->arch_info.fpu_state, + sizeof(signalFrameData->context.uc_mcontext.fpu)); + + // Fill in signalFrameData->context.uc_stack. + signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); + + // Store syscall_restart_return_value (TODO). + //signalFrameData->syscall_restart_return_value = frame->orig_rax; + + // Get the stack to use and copy the frame data to it. + uint8* userStack = get_signal_stack(thread, frame, action); + + userStack -= sizeof(*signalFrameData); + signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; + + if (user_memcpy(userSignalFrameData, signalFrameData, + sizeof(*signalFrameData)) != B_OK) { + return B_BAD_ADDRESS; + } + + // Copy a return address to the stack so that backtraces will be correct. + userStack -= sizeof(frame->ip); + if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) + return B_BAD_ADDRESS; + + // Update Thread::user_signal_context, now that everything seems to have + // gone fine. + thread->user_signal_context = &userSignalFrameData->context; + + // Set up the iframe to execute the signal handler wrapper on our prepared + // stack. First argument points to the frame data. + frame->user_sp = (addr_t)userStack; + frame->ip = ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]; + frame->di = (addr_t)userSignalFrameData; + + return B_OK; } int64 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) { - panic("arch_restore_signal_frame: TODO\n"); - return B_ERROR; + iframe* frame = x86_get_current_iframe(); + + // TODO + //frame->orig_rax = signalFrameData->syscall_restart_return_value; + + frame->ax = signalFrameData->context.uc_mcontext.rax; + frame->bx = signalFrameData->context.uc_mcontext.rbx; + frame->cx = signalFrameData->context.uc_mcontext.rcx; + frame->dx = signalFrameData->context.uc_mcontext.rdx; + frame->di = signalFrameData->context.uc_mcontext.rdi; + frame->si = signalFrameData->context.uc_mcontext.rsi; + frame->bp = signalFrameData->context.uc_mcontext.rbp; + frame->r8 = signalFrameData->context.uc_mcontext.r8; + frame->r9 = signalFrameData->context.uc_mcontext.r9; + frame->r10 = signalFrameData->context.uc_mcontext.r10; + frame->r11 = signalFrameData->context.uc_mcontext.r11; + frame->r12 = signalFrameData->context.uc_mcontext.r12; + frame->r13 = signalFrameData->context.uc_mcontext.r13; + frame->r14 = signalFrameData->context.uc_mcontext.r14; + frame->r15 = signalFrameData->context.uc_mcontext.r15; + frame->user_sp = signalFrameData->context.uc_mcontext.rsp; + frame->ip = signalFrameData->context.uc_mcontext.rip; + frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) + | (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS); + + // Same as above, alignment may not be correct. Copy to thread and restore + // from there. + Thread* thread = thread_get_current_thread(); + memcpy(thread->arch_info.fpu_state, + (void*)&signalFrameData->context.uc_mcontext.fpu, + sizeof(thread->arch_info.fpu_state)); + x86_fxrstor(thread->arch_info.fpu_state); + + // The syscall return code overwrites frame->ax with the return value of + // the syscall, need to return it here to ensure the correct value is + // restored. + return frame->ax; } diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index 579dda7d65..ccab5f8f02 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -26,6 +26,7 @@ if $(TARGET_ARCH) = x86_64 { interrupts.S stubs.cpp signals.cpp + signals_asm.S syscalls.cpp thread.cpp diff --git a/src/system/kernel/arch/x86/arch_thread.cpp b/src/system/kernel/arch/x86/arch_thread.cpp index 8b17b1d015..459ee03e3a 100644 --- a/src/system/kernel/arch/x86/arch_thread.cpp +++ b/src/system/kernel/arch/x86/arch_thread.cpp @@ -172,23 +172,6 @@ x86_initial_return_to_userland(Thread* thread, iframe* frame) } -uint8* -x86_get_signal_stack(Thread* thread, struct iframe* frame, - struct sigaction* action) -{ - // use the alternate signal stack if we should and can - if (thread->signal_stack_enabled - && (action->sa_flags & SA_ONSTACK) != 0 - && (frame->user_sp < thread->signal_stack_base - || frame->user_sp >= thread->signal_stack_base - + thread->signal_stack_size)) { - return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); - } - - return (uint8*)frame->user_sp; -} - - // #pragma mark - diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index 65339ce38d..42f7bc9a48 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -91,6 +91,7 @@ dummy() DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, context); DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, user_data); DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, handler); + DEFINE_OFFSET_MACRO(SIGNAL_FRAME_DATA, signal_frame_data, siginfo_handler); // struct ucontext_t DEFINE_OFFSET_MACRO(UCONTEXT_T, __ucontext_t, uc_mcontext); diff --git a/src/system/kernel/arch/x86/x86_signals.h b/src/system/kernel/arch/x86/x86_signals.h index 282d4afec1..0e6cb50801 100644 --- a/src/system/kernel/arch/x86/x86_signals.h +++ b/src/system/kernel/arch/x86/x86_signals.h @@ -10,7 +10,9 @@ void x86_initialize_commpage_signal_handler(); +#ifndef __x86_64__ addr_t x86_get_user_signal_handler_wrapper(bool beosHandler); +#endif #endif // _KERNEL_ARCH_X86_SIGNALS_H From ef67788fba5d738eeb99768caea7b0e5170893f5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 14:37:28 +0100 Subject: [PATCH 145/273] Ported ISA bus manager and PS/2 driver. --- build/jam/Haiku64Image | 3 ++- headers/os/drivers/ISA.h | 6 ++--- src/add-ons/kernel/bus_managers/isa/Jamfile | 3 ++- .../kernel/bus_managers/ps2/ps2_common.cpp | 14 +++++++---- .../kernel/bus_managers/ps2/ps2_dev.cpp | 24 ++++++++++--------- .../kernel/bus_managers/ps2/ps2_keyboard.cpp | 21 +++++++++------- .../kernel/bus_managers/ps2/ps2_service.cpp | 3 ++- 7 files changed, 43 insertions(+), 31 deletions(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 18bb09cdcb..bc7bc4ade7 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -40,7 +40,7 @@ PRIVATE_SYSTEM_LIBS = ; SYSTEM_SERVERS = ; -SYSTEM_ADD_ONS_BUS_MANAGERS = $(ATA_ONLY)ata pci scsi config_manager ; +SYSTEM_ADD_ONS_BUS_MANAGERS = $(ATA_ONLY)ata pci ps2 isa scsi config_manager ; SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; # modules @@ -69,6 +69,7 @@ AddNewDriversToHaikuImage disk scsi : scsi_cd scsi_disk ; # legacy drivers AddDriversToHaikuImage : console dprintf null random tty zero ; +AddDriversToHaikuImage input : ps2_hid ; # kernel AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; diff --git a/headers/os/drivers/ISA.h b/headers/os/drivers/ISA.h index 812e04b0c1..2b0f5df592 100644 --- a/headers/os/drivers/ISA.h +++ b/headers/os/drivers/ISA.h @@ -57,7 +57,7 @@ typedef struct isa_module_info { isa_dma_entry *table, /* -> caller-supplied scatter/gather table */ long num_entries /* max # entries in table */ ); - long (*start_isa_dma) ( + status_t (*start_isa_dma) ( long channel, /* dma channel to use */ void *buf, /* buffer to transfer */ long transfer_count, /* # transfers */ @@ -70,8 +70,8 @@ typedef struct isa_module_info { uchar mode, /* mode flags */ uchar emode /* extended mode flags */ ); - long (*lock_isa_dma_channel) (long channel); - long (*unlock_isa_dma_channel) (long channel); + status_t (*lock_isa_dma_channel) (long channel); + status_t (*unlock_isa_dma_channel) (long channel); } isa_module_info; #define B_ISA_MODULE_NAME "bus_managers/isa/v1" diff --git a/src/add-ons/kernel/bus_managers/isa/Jamfile b/src/add-ons/kernel/bus_managers/isa/Jamfile index 84a540a125..77719db55a 100644 --- a/src/add-ons/kernel/bus_managers/isa/Jamfile +++ b/src/add-ons/kernel/bus_managers/isa/Jamfile @@ -7,4 +7,5 @@ KernelAddon isa : : isa_arch_bus_manager.a ; -SubInclude HAIKU_TOP src add-ons kernel bus_managers isa arch $(TARGET_ARCH) ; +SubInclude HAIKU_TOP src add-ons kernel bus_managers isa arch + $(TARGET_KERNEL_ARCH) ; diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_common.cpp b/src/add-ons/kernel/bus_managers/ps2/ps2_common.cpp index 889c657247..37f902e74d 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_common.cpp +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_common.cpp @@ -117,7 +117,8 @@ ps2_selftest() uint8 in; res = ps2_command(PS2_CTRL_SELF_TEST, NULL, 0, &in, 1); if (res != B_OK || in != 0x55) { - INFO("ps2: controller self test failed, status 0x%08lx, data 0x%02x\n", res, in); + INFO("ps2: controller self test failed, status 0x%08" B_PRIx32 ", data " + "0x%02x\n", res, in); return B_ERROR; } return B_OK; @@ -131,7 +132,8 @@ ps2_setup_command_byte(bool interruptsEnabled) uint8 cmdbyte; res = ps2_command(PS2_CTRL_READ_CMD, NULL, 0, &cmdbyte, 1); - TRACE("ps2: get command byte: res 0x%08lx, cmdbyte 0x%02x\n", res, cmdbyte); + TRACE("ps2: get command byte: res 0x%08" B_PRIx32 ", cmdbyte 0x%02x\n", + res, cmdbyte); if (res != B_OK) cmdbyte = 0x47; @@ -144,7 +146,8 @@ ps2_setup_command_byte(bool interruptsEnabled) cmdbyte &= ~(PS2_BITS_KEYBOARD_INTERRUPT | PS2_BITS_AUX_INTERRUPT); res = ps2_command(PS2_CTRL_WRITE_CMD, &cmdbyte, 1, NULL, 0); - TRACE("ps2: set command byte: res 0x%08lx, cmdbyte 0x%02x\n", res, cmdbyte); + TRACE("ps2: set command byte: res 0x%08" B_PRIx32 ", cmdbyte 0x%02x\n", + res, cmdbyte); return res; } @@ -205,7 +208,8 @@ done: // This fixes bug report #1175 res = ps2_command(0xae, NULL, 0, NULL, 0); if (res != B_OK) { - INFO("ps2: active multiplexing d3 workaround failed, status 0x%08lx\n", res); + INFO("ps2: active multiplexing d3 workaround failed, status 0x%08" + B_PRIx32 "\n", res); } return B_OK; @@ -256,7 +260,7 @@ ps2_command(uint8 cmd, const uint8 *out, int outCount, uint8 *in, int inCount) #ifdef TRACE_PS2 for (i = 0; i < inCount; i++) TRACE("ps2: ps2_command in 0x%02x\n", in[i]); - TRACE("ps2: ps2_command result 0x%08lx\n", res); + TRACE("ps2: ps2_command result 0x%08" B_PRIx32 "\n", res); #endif atomic_add(&sIgnoreInterrupts, -1); diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp index e1363010d2..0cb799a5a4 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_dev.cpp @@ -203,8 +203,8 @@ ps2_dev_publish(ps2_dev *dev) } snooze(timeout / 20); } - TRACE("ps2: publishing %s: parent %s is %s; wait time %Ld\n", - dev->name, dev->parent_dev->name, + TRACE("ps2: publishing %s: parent %s is %s; wait time %" B_PRId64 + "\n", dev->name, dev->parent_dev->name, status == B_OK ? "enabled" : "busy", system_time() - start); } @@ -219,7 +219,8 @@ ps2_dev_publish(ps2_dev *dev) dev->active = true; - INFO("ps2: devfs_publish_device %s, status = 0x%08lx\n", dev->name, status); + INFO("ps2: devfs_publish_device %s, status = 0x%08" B_PRIx32 "\n", + dev->name, status); } @@ -239,8 +240,8 @@ ps2_dev_unpublish(ps2_dev *dev) if ((dev->flags & PS2_FLAG_ENABLED) && dev->disconnect) dev->disconnect(dev); - INFO("ps2: devfs_unpublish_device %s, status = 0x%08lx\n", dev->name, - status); + INFO("ps2: devfs_unpublish_device %s, status = 0x%08" B_PRIx32 "\n", + dev->name, status); } @@ -370,7 +371,8 @@ standard_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out, res = get_sem_count(dev->result_sem, &sem_count); if (res == B_OK && sem_count != 0) { - TRACE("ps2: ps2_dev_command: sem_count %ld, fixing!\n", sem_count); + TRACE("ps2: ps2_dev_command: sem_count %" B_PRId32 ", fixing!\n", + sem_count); if (sem_count > 0) acquire_sem_etc(dev->result_sem, sem_count, 0, 0); else @@ -423,8 +425,8 @@ standard_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out, if (res != B_OK) atomic_and(&dev->flags, ~PS2_FLAG_CMD); - TRACE("ps2: ps2_dev_command wait for ack res 0x%08lx, wait-time %Ld\n", - res, system_time() - start); + TRACE("ps2: ps2_dev_command wait for ack res 0x%08" B_PRIx32 ", " + "wait-time %" B_PRId64 "\n", res, system_time() - start); if (atomic_get(&dev->flags) & PS2_FLAG_ACK) { TRACE("ps2: ps2_dev_command got ACK\n"); @@ -458,15 +460,15 @@ standard_command_timeout(ps2_dev *dev, uint8 cmd, const uint8 *out, res = B_IO_ERROR; } - TRACE("ps2: ps2_dev_command wait for input res 0x%08lx, " - "wait-time %Ld\n", res, system_time() - start); + TRACE("ps2: ps2_dev_command wait for input res 0x%08" B_PRIx32 ", " + "wait-time %" B_PRId64 "\n", res, system_time() - start); for (i = 0; i < in_count; i++) TRACE("ps2: ps2_dev_command rx: 0x%02x\n", in[i]); } } - TRACE("ps2: ps2_dev_command result 0x%08lx\n", res); + TRACE("ps2: ps2_dev_command result 0x%08" B_PRIx32 "\n", res); return res; } diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp index ec6fa42e92..06a6049c08 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_keyboard.cpp @@ -88,7 +88,8 @@ set_typematic(int32 rate, bigtime_t delay) { uint8 value; - TRACE("ps2: set_typematic rate %ld, delay %Ld\n", rate, delay); + TRACE("ps2: set_typematic rate %" B_PRId32 ", delay %" B_PRId64 "\n", + rate, delay); // input server and keyboard preferences *seem* to use a range of 20-300 if (rate < 20) @@ -271,8 +272,8 @@ probe_keyboard(void) status = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], PS2_CMD_RESET, NULL, 0, &data, 1); if (status != B_OK || data != 0xaa) { - INFO("ps2: keyboard reset failed, status 0x%08lx, data 0x%02x\n", - status, data); + INFO("ps2: keyboard reset failed, status 0x%08" B_PRIx32 ", data 0x%02x" + "\n", status, data); return B_ERROR; } @@ -297,14 +298,15 @@ probe_keyboard(void) status = ps2_command(PS2_CTRL_READ_CMD, NULL, 0, &cmdbyte, 1); if (status != B_OK) { - INFO("ps2: cannot read CMD byte on kbd probe:0x%#08lx\n", status); + INFO("ps2: cannot read CMD byte on kbd probe:%#08" B_PRIx32 "\n", + status); } else if ((cmdbyte & PS2_BITS_KEYBOARD_DISABLED) == PS2_BITS_KEYBOARD_DISABLED) { cmdbyte &= ~PS2_BITS_KEYBOARD_DISABLED; status = ps2_command(PS2_CTRL_WRITE_CMD, &cmdbyte, 1, NULL, 0); if (status != B_OK) { - INFO("ps2: cannot write 0x%02x to CMD byte on kbd probe:0x%08lx\n", - cmdbyte, status); + INFO("ps2: cannot write 0x%02x to CMD byte on kbd probe:%#08" + B_PRIx32 "\n", cmdbyte, status); } } @@ -312,7 +314,7 @@ probe_keyboard(void) PS2_CMD_GET_DEVICE_ID, NULL, 0, sKeyboardIds, sizeof(sKeyboardIds)); if (status != B_OK) { - INFO("ps2: cannot read keyboard device id:0x%#08lx\n", status); + INFO("ps2: cannot read keyboard device id:%#08" B_PRIx32 "\n", status); } return B_OK; @@ -529,7 +531,8 @@ keyboard_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) case KB_SET_CONTROL_ALT_DEL_TIMEOUT: case KB_CANCEL_CONTROL_ALT_DEL: case KB_DELAY_CONTROL_ALT_DEL: - INFO("ps2: ioctl 0x%lx not implemented yet, returning B_OK\n", op); + INFO("ps2: ioctl 0x%" B_PRIx32 " not implemented yet, returning " + "B_OK\n", op); return B_OK; case KB_SET_DEBUG_READER: @@ -541,7 +544,7 @@ keyboard_ioctl(void *_cookie, uint32 op, void *buffer, size_t length) return B_OK; default: - INFO("ps2: invalid ioctl 0x%lx\n", op); + INFO("ps2: invalid ioctl 0x%" B_PRIx32 "\n", op); return B_DEV_INVALID_IOCTL; } } diff --git a/src/add-ons/kernel/bus_managers/ps2/ps2_service.cpp b/src/add-ons/kernel/bus_managers/ps2/ps2_service.cpp index 10bee95468..162c121f26 100644 --- a/src/add-ons/kernel/bus_managers/ps2/ps2_service.cpp +++ b/src/add-ons/kernel/bus_managers/ps2/ps2_service.cpp @@ -128,7 +128,8 @@ ps2_service_thread(void *arg) break; } } else { - INFO("ps2: ps2_service_thread: Error, status 0x%08lx, terminating\n", status); + INFO("ps2: ps2_service_thread: Error, status 0x%08" B_PRIx32 ", " + "terminating\n", status); break; } } From 9be774b553296a712704078314f2291ae5fc352c Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 21:27:21 +0100 Subject: [PATCH 146/273] Compilation and 64-bit fixes to libbe.so sources. Fixed the usual issues - printf format strings, uint32 instead of addr_t, etc. One thing that isn't so nice is several places where BList is used to store (u)int32, these require a double cast to addr_t then void* to silence a warning on x86_64. --- headers/os/interface/TextView.h | 2 +- src/kits/app/Application.cpp | 2 +- src/kits/app/Looper.cpp | 7 ++++--- src/kits/app/PropertyInfo.cpp | 2 +- src/kits/app/Roster.cpp | 4 ++-- src/kits/interface/Alert.cpp | 2 +- src/kits/interface/ChannelSlider.cpp | 3 ++- src/kits/interface/Menu.cpp | 6 +++--- src/kits/interface/Polygon.cpp | 7 ++++--- src/kits/interface/PrintJob.cpp | 2 +- src/kits/interface/Shelf.cpp | 4 ++-- src/kits/interface/TextView.cpp | 14 +++++++------- src/kits/interface/View.cpp | 10 +++++----- src/kits/interface/Window.cpp | 9 +++++---- src/kits/interface/layouter/ComplexLayouter.cpp | 9 ++++++--- src/kits/interface/textview_support/LineBuffer.cpp | 2 +- src/kits/interface/textview_support/LineBuffer.h | 2 +- src/kits/interface/textview_support/StyleBuffer.h | 2 +- .../interface/textview_support/TextGapBuffer.cpp | 6 +++--- src/kits/locale/DefaultCatalog.cpp | 6 +++--- src/kits/shared/QueryFile.cpp | 6 +++--- src/kits/storage/AppFileInfo.cpp | 2 +- src/kits/storage/Entry.cpp | 6 +++--- src/kits/storage/QueryPredicate.cpp | 4 ++-- src/kits/storage/disk_device/Partition.cpp | 5 +++-- src/kits/storage/disk_device/PartitioningInfo.cpp | 6 +++--- src/kits/storage/sniffer/Range.cpp | 4 ++-- src/kits/support/BufferIO.cpp | 6 +++--- 28 files changed, 74 insertions(+), 66 deletions(-) diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index 4d3e958f04..10861e24ab 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -411,7 +411,7 @@ private: void _ShowContextMenu(BPoint where); void _FilterDisallowedChars(char* text, - int32& length, text_run_array* runArray); + ssize_t& length, text_run_array* runArray); private: BPrivate::TextGapBuffer* fText; diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index 4d68d63422..3330becbdd 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -522,7 +522,7 @@ BApplication::Quit() if (!name) name = "no-name"; printf("ERROR - you must Lock the application object before calling " - "Quit(), team=%ld, looper=%s\n", Team(), name); + "Quit(), team=%" B_PRId32 ", looper=%s\n", Team(), name); unlock = true; if (!Lock()) return; diff --git a/src/kits/app/Looper.cpp b/src/kits/app/Looper.cpp index 2d1879dbcb..1713e99cb9 100644 --- a/src/kits/app/Looper.cpp +++ b/src/kits/app/Looper.cpp @@ -443,7 +443,8 @@ BLooper::Quit() if (!IsLocked()) { printf("ERROR - you must Lock a looper before calling Quit(), " - "team=%ld, looper=%s\n", Team(), Name() ? Name() : "unnamed"); + "team=%" B_PRId32 ", looper=%s\n", Team(), + Name() ? Name() : "unnamed"); } // Try to lock @@ -547,7 +548,7 @@ BLooper::IsLocked() const } uint32 stack; - return ((uint32)&stack & ~(B_PAGE_SIZE - 1)) == fCachedStack + return ((addr_t)&stack & ~(B_PAGE_SIZE - 1)) == fCachedStack || find_thread(NULL) == fOwner; } @@ -1338,7 +1339,7 @@ BLooper::check_lock() // It is used in situations where it's clear that the looper is valid, // ie. from handlers uint32 stack; - if (((uint32)&stack & ~(B_PAGE_SIZE - 1)) == fCachedStack + if (((addr_t)&stack & ~(B_PAGE_SIZE - 1)) == fCachedStack || fOwner == find_thread(NULL)) return; diff --git a/src/kits/app/PropertyInfo.cpp b/src/kits/app/PropertyInfo.cpp index 10f45b3e09..e09c4863b3 100644 --- a/src/kits/app/PropertyInfo.cpp +++ b/src/kits/app/PropertyInfo.cpp @@ -426,7 +426,7 @@ BPropertyInfo::PrintToStream() const // specifiers for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) { uint32 spec = fPropInfo[pi].specifiers[i]; - printf("%lu", spec); + printf("%" B_PRIu32, spec); } printf("\n"); } diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index a500c70dd7..051d200270 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -657,7 +657,7 @@ BRoster::GetAppList(BList* teamIDList) const if (reply.what == B_REG_SUCCESS) { team_id team; for (int32 i = 0; reply.FindInt32("teams", i, &team) == B_OK; i++) - teamIDList->AddItem((void*)team); + teamIDList->AddItem((void*)(addr_t)team); } else { if (reply.FindInt32("error", &error) != B_OK) error = B_ERROR; @@ -700,7 +700,7 @@ BRoster::GetAppList(const char* sig, BList* teamIDList) const if (reply.what == B_REG_SUCCESS) { team_id team; for (int32 i = 0; reply.FindInt32("teams", i, &team) == B_OK; i++) - teamIDList->AddItem((void*)team); + teamIDList->AddItem((void*)(addr_t)team); } else if (reply.FindInt32("error", &error) != B_OK) error = B_ERROR; } diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index b6ec85cfa4..ed53bb17d9 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -697,7 +697,7 @@ BAlert::_CreateButton(int32 which, const char* label) rect.bottom = rect.top; char name[32]; - snprintf(name, sizeof(name), "_b%ld_", which); + snprintf(name, sizeof(name), "_b%" B_PRId32 "_", which); BButton* button = new(std::nothrow) BButton(rect, name, label, message, B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); diff --git a/src/kits/interface/ChannelSlider.cpp b/src/kits/interface/ChannelSlider.cpp index c2d6040a3d..02e90a9470 100644 --- a/src/kits/interface/ChannelSlider.cpp +++ b/src/kits/interface/ChannelSlider.cpp @@ -839,7 +839,8 @@ BChannelSlider::_DrawThumbs() // draw some kind of current value tool tip if (fCurrentChannel != -1 && fMinPoint != 0) { char valueString[32]; - snprintf(valueString, 32, "%ld", ValueFor(fCurrentChannel)); + snprintf(valueString, 32, "%" B_PRId32, + ValueFor(fCurrentChannel)); float stringWidth = fBackingView->StringWidth(valueString); float width = max_c(10.0, stringWidth); BRect valueRect(0.0, 0.0, width, 10.0); diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index c8692063d9..2e8e423c5e 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -68,9 +68,9 @@ public: // TODO: make this work with Unicode characters! bool HasTrigger(uint32 c) - { return fList.HasItem((void*)tolower(c)); } + { return fList.HasItem((void*)(addr_t)tolower(c)); } bool AddTrigger(uint32 c) - { return fList.AddItem((void*)tolower(c)); } + { return fList.AddItem((void*)(addr_t)tolower(c)); } private: BList fList; @@ -2883,7 +2883,7 @@ bool BMenu::_OkToProceed(BMenuItem* item, bool keyDown) { BPoint where; - ulong buttons; + uint32 buttons; GetMouse(&where, &buttons, false); bool stickyMode = _IsStickyMode(); // Quit if user clicks the mouse button in sticky mode diff --git a/src/kits/interface/Polygon.cpp b/src/kits/interface/Polygon.cpp index 07c27ba55c..0728b785ad 100644 --- a/src/kits/interface/Polygon.cpp +++ b/src/kits/interface/Polygon.cpp @@ -157,15 +157,16 @@ BPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds) if (points == NULL || count <= 0) return false; if (count > MAX_POINT_COUNT || (fCount + count) > MAX_POINT_COUNT) { - fprintf(stderr, "BPolygon::_AddPoints(%ld) - too many points\n", - count); + fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") - too many points" + "\n", count); return false; } BPoint* newPoints = (BPoint*)realloc(fPoints, (fCount + count) * sizeof(BPoint)); if (newPoints == NULL) { - fprintf(stderr, "BPolygon::_AddPoints(%ld) out of memory\n", count); + fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") out of memory\n", + count); return false; } diff --git a/src/kits/interface/PrintJob.cpp b/src/kits/interface/PrintJob.cpp index d21f27fa09..83efdf7e1a 100644 --- a/src/kits/interface/PrintJob.cpp +++ b/src/kits/interface/PrintJob.cpp @@ -575,7 +575,7 @@ BPrintJob::_RecurseView(BView* view, BPoint origin, BPicture* picture, void BPrintJob::_GetMangledName(char* buffer, size_t bufferSize) const { - snprintf(buffer, bufferSize, "%s@%lld", fPrintJobName, + snprintf(buffer, bufferSize, "%s@%" B_PRId64, fPrintJobName, system_time() / 1000); } diff --git a/src/kits/interface/Shelf.cpp b/src/kits/interface/Shelf.cpp index bcd75b979c..0ffdf5671d 100644 --- a/src/kits/interface/Shelf.cpp +++ b/src/kits/interface/Shelf.cpp @@ -557,7 +557,7 @@ BShelf::~BShelf() while (fReplicants.CountItems() > 0) { replicant_data *data = (replicant_data *)fReplicants.ItemAt(0); - fReplicants.RemoveItem(0L); + fReplicants.RemoveItem((int32)0); delete data; } } @@ -1003,7 +1003,7 @@ BShelf::ReplicantAt(int32 index, BView **_view, uint32 *_uniqueID, if (_view) *_view = NULL; if (_uniqueID) - *_uniqueID = ~0UL; + *_uniqueID = ~(uint32)0; if (_error) *_error = B_BAD_INDEX; diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index d46414d982..855731f52a 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -731,7 +731,7 @@ BTextView::WindowActivated(bool state) } BPoint where; - ulong buttons; + uint32 buttons; GetMouse(&where, &buttons, false); if (Bounds().Contains(where)) @@ -3241,7 +3241,7 @@ BTextView::_InitObject(BRect textRect, const BFont *initialFont, fSelectable = true; fEditable = true; fWrap = true; - fMaxBytes = LONG_MAX; + fMaxBytes = INT32_MAX; fDisallowedChars = NULL; fAlignment = B_ALIGN_LEFT; fAutoindent = false; @@ -5036,7 +5036,7 @@ BTextView::_Activate() _ShowCaret(); BPoint where; - ulong buttons; + uint32 buttons; GetMouse(&where, &buttons, false); if (Bounds().Contains(where)) _TrackMouse(where, NULL); @@ -5600,7 +5600,7 @@ BTextView::_ShowContextMenu(BPoint where) void -BTextView::_FilterDisallowedChars(char* text, int32& length, +BTextView::_FilterDisallowedChars(char* text, ssize_t& length, text_run_array* runArray) { if (!fDisallowedChars) @@ -5609,9 +5609,9 @@ BTextView::_FilterDisallowedChars(char* text, int32& length, if (fDisallowedChars->IsEmpty() || !text) return; - int32 stringIndex = 0; + ssize_t stringIndex = 0; if (runArray) { - int32 remNext = 0; + ssize_t remNext = 0; for (int i = 0; i < runArray->count; i++) { runArray->runs[i].offset -= remNext; @@ -5669,7 +5669,7 @@ void BTextView::TextTrackState::SimulateMouseMovement(BTextView *textView) { BPoint where; - ulong buttons; + uint32 buttons; // When the mouse cursor is still and outside the textview, // no B_MOUSE_MOVED message are sent, obviously. But scrolling // has to work neverthless, so we "fake" a MouseMoved() call here. diff --git a/src/kits/interface/View.cpp b/src/kits/interface/View.cpp index efbe9549a6..615226071b 100644 --- a/src/kits/interface/View.cpp +++ b/src/kits/interface/View.cpp @@ -5882,8 +5882,8 @@ BView::_PrintToStream() "\tNextSibling: %s\n" "\tPrevSibling: %s\n" "\tOwner(Window): %s\n" - "\tToken: %ld\n" - "\tFlags: %ld\n" + "\tToken: %" B_PRId32 "\n" + "\tFlags: %" B_PRId32 "\n" "\tView origin: (%f,%f)\n" "\tView Bounds rectangle: (%f,%f,%f,%f)\n" "\tShow level: %d\n" @@ -5893,8 +5893,8 @@ BView::_PrintToStream() "\tHorizontal Scrollbar %s\n" "\tIs Printing?: %s\n" "\tShelf?: %s\n" - "\tEventMask: %ld\n" - "\tEventOptions: %ld\n", + "\tEventMask: %" B_PRId32 "\n" + "\tEventOptions: %" B_PRId32 "\n", Name(), fParent ? fParent->Name() : "NULL", fFirstChild ? fFirstChild->Name() : "NULL", @@ -5922,7 +5922,7 @@ BView::_PrintToStream() "\t\tHighColor: [%d,%d,%d,%d]\n" "\t\tLowColor: [%d,%d,%d,%d]\n" "\t\tViewColor: [%d,%d,%d,%d]\n" - "\t\tPattern: %llx\n" + "\t\tPattern: %" B_PRIx64 "\n" "\t\tDrawingMode: %d\n" "\t\tLineJoinMode: %d\n" "\t\tLineCapMode: %d\n" diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 8292e52158..07278cec6e 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -515,7 +515,7 @@ BWindow::Quit() name = "no-name"; printf("ERROR - you must Lock a looper before calling Quit(), " - "team=%ld, looper=%s\n", Team(), name); + "team=%" B_PRId32 ", looper=%s\n", Team(), name); } // Try to lock @@ -1032,7 +1032,8 @@ BWindow::DispatchMessage(BMessage* msg, BHandler* target) be_roster->GetAppList(info.signature, &list); for (int32 i = 0; i < list.CountItems(); i++) { - do_minimize_team(BRect(), (team_id)list.ItemAt(i), false); + do_minimize_team(BRect(), (team_id)(addr_t)list.ItemAt(i), + false); } break; } @@ -1433,8 +1434,8 @@ FrameMoved(origin); if (BView* view = _FindView(info->token)) view->_Draw(info->updateRect); else { - printf("_UPDATE_ - didn't find view by token: %ld\n", - info->token); + printf("_UPDATE_ - didn't find view by token: %" + B_PRId32 "\n", info->token); } //drawTime += system_time() - drawStart; } diff --git a/src/kits/interface/layouter/ComplexLayouter.cpp b/src/kits/interface/layouter/ComplexLayouter.cpp index 00f559a7a1..c694bda059 100644 --- a/src/kits/interface/layouter/ComplexLayouter.cpp +++ b/src/kits/interface/layouter/ComplexLayouter.cpp @@ -85,9 +85,12 @@ public: void Dump() { - printf("ComplexLayouter::MyLayoutInfo(): %ld elements:\n", fCount); - for (int32 i = 0; i < fCount + 1; i++) - printf(" %2ld: location: %4ld\n", i, fLocations[i]); + printf("ComplexLayouter::MyLayoutInfo(): %" B_PRId32 " elements:\n", + fCount); + for (int32 i = 0; i < fCount + 1; i++) { + printf(" %2" B_PRId32 ": location: %4" B_PRId32 "\n", i, + fLocations[i]); + } } public: diff --git a/src/kits/interface/textview_support/LineBuffer.cpp b/src/kits/interface/textview_support/LineBuffer.cpp index 82c38e55a6..35c0c0772c 100644 --- a/src/kits/interface/textview_support/LineBuffer.cpp +++ b/src/kits/interface/textview_support/LineBuffer.cpp @@ -94,7 +94,7 @@ BTextView::LineBuffer::PixelToLine(float pixel) const void -BTextView::LineBuffer::BumpOrigin(float delta, long index) +BTextView::LineBuffer::BumpOrigin(float delta, int32 index) { for (long i = index; i < fItemCount; i++) fBuffer[i].origin += delta; diff --git a/src/kits/interface/textview_support/LineBuffer.h b/src/kits/interface/textview_support/LineBuffer.h index a32758bbde..81e124eb78 100644 --- a/src/kits/interface/textview_support/LineBuffer.h +++ b/src/kits/interface/textview_support/LineBuffer.h @@ -39,7 +39,7 @@ public: void BumpOrigin(float delta, int32 index); void BumpOffset(int32 delta, int32 index); - long NumLines() const; + int32 NumLines() const; float MaxWidth() const; STELine* operator[](int32 index) const; }; diff --git a/src/kits/interface/textview_support/StyleBuffer.h b/src/kits/interface/textview_support/StyleBuffer.h index 227fc91e9e..9b289a24b2 100644 --- a/src/kits/interface/textview_support/StyleBuffer.h +++ b/src/kits/interface/textview_support/StyleBuffer.h @@ -56,7 +56,7 @@ class _BStyleRunDescBuffer_ : public _BTextViewSupportBuffer_ { void InsertDesc(STEStyleRunDesc* inDesc, int32 index); void RemoveDescs(int32 index, int32 count = 1); - long OffsetToRun(int32 offset) const; + int32 OffsetToRun(int32 offset) const; void BumpOffset(int32 delta, int32 index); STEStyleRunDesc* operator[](int32 index) const; diff --git a/src/kits/interface/textview_support/TextGapBuffer.cpp b/src/kits/interface/textview_support/TextGapBuffer.cpp index af122f0c6c..bc4de30dc2 100644 --- a/src/kits/interface/textview_support/TextGapBuffer.cpp +++ b/src/kits/interface/textview_support/TextGapBuffer.cpp @@ -188,7 +188,7 @@ TextGapBuffer::GetString(int32 fromOffset, int32* _numBytes) bool -TextGapBuffer::FindChar(char inChar, long fromIndex, long* ioDelta) +TextGapBuffer::FindChar(char inChar, int32 fromIndex, int32* ioDelta) { long numChars = *ioDelta; for (long i = 0; i < numChars; i++) { @@ -333,7 +333,7 @@ TextGapBuffer::_MoveGapTo(int32 toIndex) void -TextGapBuffer::_EnlargeGapTo(long inCount) +TextGapBuffer::_EnlargeGapTo(int32 inCount) { if (inCount == fGapCount) return; @@ -348,7 +348,7 @@ TextGapBuffer::_EnlargeGapTo(long inCount) void -TextGapBuffer::_ShrinkGapTo(long inCount) +TextGapBuffer::_ShrinkGapTo(int32 inCount) { if (inCount == fGapCount) return; diff --git a/src/kits/locale/DefaultCatalog.cpp b/src/kits/locale/DefaultCatalog.cpp index dbb913d952..43a39d06b2 100644 --- a/src/kits/locale/DefaultCatalog.cpp +++ b/src/kits/locale/DefaultCatalog.cpp @@ -359,7 +359,7 @@ DefaultCatalog::WriteToFile(const char *path) return res; BMallocIO mallocIO; - mallocIO.SetBlockSize(max(fCatMap.Size() * 20, 256L)); + mallocIO.SetBlockSize(max(fCatMap.Size() * 20, (int32)256)); // set a largish block-size in order to avoid reallocs res = Flatten(&mallocIO); if (res == B_OK) { @@ -390,7 +390,7 @@ DefaultCatalog::WriteToAttribute(const entry_ref &appOrAddOnRef) return res; BMallocIO mallocIO; - mallocIO.SetBlockSize(max(fCatMap.Size() * 20, 256L)); + mallocIO.SetBlockSize(max(fCatMap.Size() * 20, (int32)256)); // set a largish block-size in order to avoid reallocs res = Flatten(&mallocIO); @@ -421,7 +421,7 @@ DefaultCatalog::WriteToResource(const entry_ref &appOrAddOnRef) return res; BMallocIO mallocIO; - mallocIO.SetBlockSize(max(fCatMap.Size() * 20, 256L)); + mallocIO.SetBlockSize(max(fCatMap.Size() * 20, (int32)256)); // set a largish block-size in order to avoid reallocs res = Flatten(&mallocIO); diff --git a/src/kits/shared/QueryFile.cpp b/src/kits/shared/QueryFile.cpp index 05314be9bb..159c4101c6 100644 --- a/src/kits/shared/QueryFile.cpp +++ b/src/kits/shared/QueryFile.cpp @@ -180,14 +180,14 @@ BQueryFile::SetPredicate(const char* predicate) status_t BQueryFile::AddVolume(const BVolume& volume) { - return fVolumes.AddItem((void*)volume.Device()) ? B_OK : B_NO_MEMORY; + return fVolumes.AddItem((void*)(addr_t)volume.Device()) ? B_OK : B_NO_MEMORY; } status_t BQueryFile::AddVolume(dev_t device) { - return fVolumes.AddItem((void*)device) ? B_OK : B_NO_MEMORY; + return fVolumes.AddItem((void*)(addr_t)device) ? B_OK : B_NO_MEMORY; } @@ -211,7 +211,7 @@ BQueryFile::VolumeAt(int32 index) const if (index < 0 || index >= fVolumes.CountItems()) return -1; - return (dev_t)fVolumes.ItemAt(index); + return (dev_t)(addr_t)fVolumes.ItemAt(index); } diff --git a/src/kits/storage/AppFileInfo.cpp b/src/kits/storage/AppFileInfo.cpp index fb9581e52e..ad81175416 100644 --- a/src/kits/storage/AppFileInfo.cpp +++ b/src/kits/storage/AppFileInfo.cpp @@ -1430,7 +1430,7 @@ BAppFileInfo::_ReadData(const char* name, int32 id, type_code type, error = B_NO_MEMORY; bufferSize = info.size; } - if (error == B_OK && bufferSize < info.size) + if (error == B_OK && (off_t)bufferSize < info.size) error = B_BAD_VALUE; // read the data diff --git a/src/kits/storage/Entry.cpp b/src/kits/storage/Entry.cpp index 7ff8715695..be0edd0f12 100644 --- a/src/kits/storage/Entry.cpp +++ b/src/kits/storage/Entry.cpp @@ -684,14 +684,14 @@ BEntry::_Dump(const char* name) printf("------------------------------------------------------------\n"); } - printf("fCStatus == %ld\n", fCStatus); + printf("fCStatus == %" B_PRId32 "\n", fCStatus); struct stat st; if (fDirFd != -1 && _kern_read_stat(fDirFd, NULL, false, &st, sizeof(struct stat)) == B_OK) { - printf("dir.device == %ld\n", st.st_dev); - printf("dir.inode == %lld\n", st.st_ino); + printf("dir.device == %" B_PRIdDEV "\n", st.st_dev); + printf("dir.inode == %" B_PRIdINO "\n", st.st_ino); } else { printf("dir == NullFd\n"); } diff --git a/src/kits/storage/QueryPredicate.cpp b/src/kits/storage/QueryPredicate.cpp index 997c5dda13..bb48f961cc 100644 --- a/src/kits/storage/QueryPredicate.cpp +++ b/src/kits/storage/QueryPredicate.cpp @@ -272,7 +272,7 @@ ValueNode::GetString(BString &predicate) } value; value.asFloat = fValue; // int32 value = *reinterpret_cast(&fValue); - sprintf(buffer, "0x%08lx", value.asInteger); + sprintf(buffer, "0x%08" B_PRIx32, value.asInteger); predicate.SetTo(buffer); return B_OK; } @@ -289,7 +289,7 @@ ValueNode::GetString(BString &predicate) } value; // int64 value = *reinterpret_cast(&fValue); value.asFloat = fValue; - sprintf(buffer, "0x%016Lx", value.asInteger); + sprintf(buffer, "0x%016" B_PRIx64, value.asInteger); predicate.SetTo(buffer); return B_OK; } diff --git a/src/kits/storage/disk_device/Partition.cpp b/src/kits/storage/disk_device/Partition.cpp index 8bd5fea703..3dbcadd60b 100644 --- a/src/kits/storage/disk_device/Partition.cpp +++ b/src/kits/storage/disk_device/Partition.cpp @@ -354,10 +354,11 @@ BPartition::GetPath(BPath* path) const if (!leaf || strcmp(leaf, "raw") != B_OK) return B_ERROR; - snprintf(indexBuffer, sizeof(indexBuffer), "%ld", Index()); + snprintf(indexBuffer, sizeof(indexBuffer), "%" B_PRId32, Index()); } else { // Our parent is a normal partition, no device: Append our index. - snprintf(indexBuffer, sizeof(indexBuffer), "%s_%ld", path->Leaf(), Index()); + snprintf(indexBuffer, sizeof(indexBuffer), "%s_%" B_PRId32, + path->Leaf(), Index()); } error = path->GetParent(path); diff --git a/src/kits/storage/disk_device/PartitioningInfo.cpp b/src/kits/storage/disk_device/PartitioningInfo.cpp index 19abfe8296..0e0cba3c90 100644 --- a/src/kits/storage/disk_device/PartitioningInfo.cpp +++ b/src/kits/storage/disk_device/PartitioningInfo.cpp @@ -220,10 +220,10 @@ BPartitioningInfo::PrintToStream() const printf("BPartitioningInfo is not initialized\n"); return; } - printf("BPartitioningInfo has %ld spaces:\n", fCount); + printf("BPartitioningInfo has %" B_PRId32 " spaces:\n", fCount); for (int32 i = 0; i < fCount; i++) { - printf(" space at %ld: offset = %lld, size = %lld\n", - i, fSpaces[i].offset, fSpaces[i].size); + printf(" space at %" B_PRId32 ": offset = %" B_PRId64 ", size = %" + B_PRId64 "\n", i, fSpaces[i].offset, fSpaces[i].size); } } diff --git a/src/kits/storage/sniffer/Range.cpp b/src/kits/storage/sniffer/Range.cpp index 2f994f7970..ebf64711a5 100644 --- a/src/kits/storage/sniffer/Range.cpp +++ b/src/kits/storage/sniffer/Range.cpp @@ -34,8 +34,8 @@ Range::GetErr() const { else { char start_str[32]; char end_str[32]; - sprintf(start_str, "%ld", fStart); - sprintf(end_str, "%ld", fEnd); + sprintf(start_str, "%" B_PRId32, fStart); + sprintf(end_str, "%" B_PRId32, fEnd); return new Err(std::string("Sniffer Parser Error -- Invalid range: [") + start_str + ":" + end_str + "]", -1); } } diff --git a/src/kits/support/BufferIO.cpp b/src/kits/support/BufferIO.cpp index f6d1cc9afd..a64d611c4e 100644 --- a/src/kits/support/BufferIO.cpp +++ b/src/kits/support/BufferIO.cpp @@ -71,7 +71,7 @@ BBufferIO::ReadAt(off_t pos, void* buffer, size_t size) // If the data we are looking for is not in the buffer... if (size > fBufferUsed || pos < fBufferStart - || pos > fBufferStart + fBufferUsed + || pos > fBufferStart + (off_t)fBufferUsed || pos + size > fBufferStart + fBufferUsed) { if (fBufferIsDirty) { // If there are pending writes, do them. @@ -119,7 +119,7 @@ BBufferIO::WriteAt(off_t pos, const void* buffer, size_t size) } // If we want to write beyond the cached data... - if (pos > fBufferStart + fBufferUsed + if (pos > fBufferStart + (off_t)fBufferUsed || pos < fBufferStart) { ssize_t read; off_t where = pos; @@ -245,7 +245,7 @@ BBufferIO::PrintToStream() const { printf("stream %p\n", fStream); printf("buffer %p\n", fBuffer); - printf("start %lld\n", fBufferStart); + printf("start %" B_PRId64 "\n", fBufferStart); printf("used %ld\n", fBufferUsed); printf("phys %ld\n", fBufferSize); printf("dirty %s\n", (fBufferIsDirty) ? "true" : "false"); From 533f3bb494fc873564146561b6b954168021c6d1 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 21:34:05 +0100 Subject: [PATCH 147/273] Support x86_64 in sysinfo. Just changed all #ifdef __INTEL__ to __INTEL__ || __x86_64__, and fixed all the printf format strings. The CPU detection code all works the same. --- headers/private/shared/cpu_type.h | 14 +++--- src/bin/sysinfo.cpp | 81 ++++++++++++++++++------------- 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/headers/private/shared/cpu_type.h b/headers/private/shared/cpu_type.h index 2c1f7c6f77..dbc1e3f8ad 100644 --- a/headers/private/shared/cpu_type.h +++ b/headers/private/shared/cpu_type.h @@ -34,7 +34,7 @@ get_cpu_vendor_string(enum cpu_types type) /* We're not that nice here. */ return "IBM/Motorola"; #endif -#if __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) /* Determine x86 vendor name */ switch (type & B_CPU_x86_VENDOR_MASK) { case B_CPU_INTEL_x86: @@ -60,7 +60,7 @@ get_cpu_vendor_string(enum cpu_types type) } -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) /* Parameter 'name' needs to point to an allocated array of 49 characters. */ void get_cpuid_model_string(char *name) @@ -115,16 +115,16 @@ get_cpuid_model_string(char *name) } } } -#endif /* __INTEL__ */ +#endif /* __INTEL__ || __x86_64__ */ const char * get_cpu_model_string(system_info *info) { -#if __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) char cpuidName[49]; /* for use with get_cpuid_model_string() */ -#endif /* __INTEL__ */ +#endif /* __INTEL__ || __x86_64__ */ /* Determine CPU type */ switch (info->cpu_type) { @@ -140,7 +140,7 @@ get_cpu_model_string(system_info *info) case B_CPU_PPC_604e: return "604e"; #endif /* __POWERPC__ */ -#if __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) case B_CPU_x86: return "Unknown x86"; @@ -342,7 +342,7 @@ get_cpu_model_string(system_info *info) /* National Semiconductor */ case B_CPU_NATIONAL_GEODE_GX1: return "Geode GX1"; -#endif /* __INTEL__ */ +#endif /* __INTEL__ || __x86_64__ */ default: return NULL; diff --git a/src/bin/sysinfo.cpp b/src/bin/sysinfo.cpp index 52a9f8d641..30ce3c7aef 100644 --- a/src/bin/sysinfo.cpp +++ b/src/bin/sysinfo.cpp @@ -17,7 +17,7 @@ // ToDo: -disable_cpu_sn option is not yet implemented // ToDo: most of this file should go into an architecture dependent source file -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) struct cache_description { uint8 code; @@ -210,7 +210,7 @@ print_intel_cache_descriptors(enum cpu_types type, cpuid_info *info) } } -#endif // __INTEL__ +#endif // __INTEL__ || __x86_64__ static void @@ -245,14 +245,15 @@ print_level2_cache(uint32 reg, const char *name) uint32 linesPerTag = (reg >> 8) & 0xf; // intel does not define this uint32 lineSize = reg & 0xff; - printf("\t%s: %lu KB, ", name, size); + printf("\t%s: %" B_PRIu32 " KB, ", name, size); if (ways == 0xf) printf("fully associative, "); else if (ways == 0x1) printf("direct-mapped, "); else printf("%lu-way set associative, ", 1UL << (ways / 2)); - printf("%lu lines/tag, %lu bytes/line\n", linesPerTag, lineSize); + printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, + lineSize); } @@ -264,16 +265,17 @@ print_level1_cache(uint32 reg, const char *name) uint32 linesPerTag = (reg >> 8) & 0xff; uint32 lineSize = reg & 0xff; - printf("\t%s: %lu KB, ", name, size); + printf("\t%s: %" B_PRIu32 " KB, ", name, size); if (ways == 0xff) printf("fully associative, "); else - printf("%lu-way set associative, ", ways); - printf("%lu lines/tag, %lu bytes/line\n", linesPerTag, lineSize); + printf("%" B_PRIu32 "-way set associative, ", ways); + printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, + lineSize); } -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) static void print_cache_desc(int32 cpu) @@ -315,7 +317,7 @@ print_intel_cache_desc(int32 cpu) uint32 sets = info.regs.ecx; - printf("\tL%ld ",level); + printf("\tL%" B_PRId32 " ",level); switch (type) { case 1: printf("Data cache "); break; @@ -327,8 +329,9 @@ print_intel_cache_desc(int32 cpu) if (isFullyAssoc) printf("fully associative, "); else - printf("%lu-way set associative, ", ways); - printf("%lu lines/tag, %lu bytes/line\n", linesPerTag, lineSize); + printf("%" B_PRIu32 "-way set associative, ", ways); + printf("%" B_PRIu32 " lines/tag, %" B_PRIu32 " bytes/line\n", linesPerTag, + lineSize); get_cpuid(&info, 0x80000006, cpu); print_level2_cache(sets, "L2 cache"); @@ -342,7 +345,7 @@ print_transmeta_features(uint32 features) printf("\t\tFCMOV\n"); } -#endif // __INTEL__ +#endif // __INTEL__ || __x86_64__ static void @@ -456,14 +459,15 @@ print_features(uint32 features) } -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) static void print_processor_signature(system_info *sys_info, cpuid_info *info, const char *prefix) { if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_AMD_x86) { - printf("\t%s%sype %lu, family %lu, model %u, stepping %lu, features 0x%08lx\n", + printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %u, " + "stepping %" B_PRIu32 ", features 0x%08" B_PRIx32 "\n", prefix ? prefix : "", prefix && prefix[0] ? "t" : "T", info->eax_1.type, info->eax_1.family + (info->eax_1.family == 0xf ? info->eax_1.extended_family : 0), @@ -472,7 +476,8 @@ print_processor_signature(system_info *sys_info, cpuid_info *info, const char *p info->eax_1.features); } else if ((sys_info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86) { // model calculation is different for INTEL - printf("\t%s%sype %lu, family %lu, model %u, stepping %lu, features 0x%08lx\n", + printf("\t%s%sype %" B_PRIu32 ", family %" B_PRIu32 ", model %u, " + "stepping %" B_PRIu32 ", features 0x%08" B_PRIx32 "\n", prefix ? prefix : "", prefix && prefix[0] ? "t" : "T", info->eax_1.type, info->eax_1.family + (info->eax_1.family == 0xf ? info->eax_1.extended_family : 0), @@ -482,7 +487,7 @@ print_processor_signature(system_info *sys_info, cpuid_info *info, const char *p } } -#endif // __INTEL__ +#endif // __INTEL__ || __x86_64__ static void @@ -495,7 +500,7 @@ dump_platform(system_info *info) } -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) static void dump_cpu(system_info *info, int32 cpu) @@ -551,15 +556,15 @@ dump_cpu(system_info *info, int32 cpu) // the BIOS may not have set the processor name if (name[0]) - printf("CPU #%ld: \"%s\"\n", cpu, name); + printf("CPU #%" B_PRId32 ": \"%s\"\n", cpu, name); else { // Intel CPUs don't seem to have the genuine vendor field - printf("CPU #%ld: %.12s\n", cpu, + printf("CPU #%" B_PRId32 ": %.12s\n", cpu, (info->cpu_type & B_CPU_x86_VENDOR_MASK) == B_CPU_INTEL_x86 ? baseInfo.eax_0.vendor_id : cpuInfo.eax_0.vendor_id); } } else { - printf("CPU #%ld: %.12s\n", cpu, baseInfo.eax_0.vendor_id); + printf("CPU #%" B_PRId32 ": %.12s\n", cpu, baseInfo.eax_0.vendor_id); if (maxStandardFunction == 0) return; } @@ -570,7 +575,7 @@ dump_cpu(system_info *info, int32 cpu) if (maxStandardFunction >= 1) { /* Extended features */ - printf("\tExtended Intel: 0x%08lx\n", cpuInfo.eax_1.extended_features); + printf("\tExtended Intel: 0x%08" B_PRIx32 "\n", cpuInfo.eax_1.extended_features); print_extended_features(cpuInfo.eax_1.extended_features); } @@ -619,7 +624,8 @@ dump_cpu(system_info *info, int32 cpu) if (flagsInfo.eax_1.features & (1UL << 18)) { get_cpuid(&cpuInfo, 3, cpu); - printf("Serial number: %04lx-%04lx-%04lx-%04lx-%04lx-%04lx\n", + printf("Serial number: %04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 + "-%04" B_PRIx32 "-%04" B_PRIx32 "-%04" B_PRIx32 "\n", flagsInfo.eax_1.features >> 16, flagsInfo.eax_1.features & 0xffff, cpuInfo.regs.edx >> 16, cpuInfo.regs.edx & 0xffff, cpuInfo.regs.ecx >> 16, cpuInfo.regs.edx & 0xffff); @@ -629,7 +635,7 @@ dump_cpu(system_info *info, int32 cpu) putchar('\n'); } -#endif // __INTEL__ +#endif // __INTEL__ || __x86_64__ static void @@ -646,28 +652,30 @@ dump_cpus(system_info *info) snprintf(modelString, 32, "(Unknown %x)", info->cpu_type); } - printf("%ld %s%s%s, revision %04lx running at %LdMHz (ID: 0x%08lx 0x%08lx)\n\n", + printf("%" B_PRId32 " %s%s%s, revision %04" B_PRIx32 " running at %" + B_PRId64 "MHz (ID: 0x%08" B_PRIx32 " 0x%08" B_PRIx32 ")\n\n", info->cpu_count, vendor ? vendor : "", vendor ? " " : "", model, info->cpu_revision, info->cpu_clock_speed / 1000000, info->id[0], info->id[1]); -#ifdef __INTEL__ +#if defined(__INTEL__) || defined(__x86_64__) for (int32 cpu = 0; cpu < info->cpu_count; cpu++) dump_cpu(info, cpu); -#endif // __INTEL__ +#endif // __INTEL__ || __x86_64__ } static void dump_mem(system_info *info) { - printf("%10lu bytes free (used/max %10lu / %10lu)\n", + printf("%10" B_PRIu32 " bytes free (used/max %10" B_PRIu32 " / %10" + B_PRIu32 ")\n", B_PAGE_SIZE * (uint32)(info->max_pages - info->used_pages), B_PAGE_SIZE * (uint32)info->used_pages, B_PAGE_SIZE * (uint32)info->max_pages); - printf(" (cached %10lu)\n", + printf(" (cached %10" B_PRIu32 ")\n", B_PAGE_SIZE * (uint32)info->cached_pages); } @@ -675,7 +683,8 @@ dump_mem(system_info *info) static void dump_sem(system_info *info) { - printf("%10ld semaphores free (used/max %10ld / %10ld)\n", + printf("%10" B_PRId32 " semaphores free (used/max %10" B_PRId32 " / %10" + B_PRId32 ")\n", info->max_sems - info->used_sems, info->used_sems, info->max_sems); } @@ -684,7 +693,8 @@ dump_sem(system_info *info) static void dump_ports(system_info *info) { - printf("%10ld ports free (used/max %10ld / %10ld)\n", + printf("%10" B_PRId32 " ports free (used/max %10" B_PRId32 " / %10" + B_PRId32 ")\n", info->max_ports - info->used_ports, info->used_ports, info->max_ports); } @@ -693,7 +703,8 @@ dump_ports(system_info *info) static void dump_thread(system_info *info) { - printf("%10ld threads free (used/max %10ld / %10ld)\n", + printf("%10" B_PRId32 " threads free (used/max %10" B_PRId32 " / %10" + B_PRId32 ")\n", info->max_threads - info->used_threads, info->used_threads, info->max_threads); } @@ -702,7 +713,8 @@ dump_thread(system_info *info) static void dump_team(system_info *info) { - printf("%10ld teams free (used/max %10ld / %10ld)\n", + printf("%10" B_PRId32 " teams free (used/max %10" B_PRId32 " / %10" + B_PRId32 ")\n", info->max_teams - info->used_teams, info->used_teams, info->max_teams); } @@ -711,7 +723,7 @@ dump_team(system_info *info) static void dump_kinfo(system_info *info) { - printf("Kernel name: %s built on: %s %s version 0x%Lx\n", + printf("Kernel name: %s built on: %s %s version 0x%" B_PRIx64 "\n", info->kernel_name, info->kernel_build_date, info->kernel_build_time, info->kernel_version ); @@ -752,7 +764,8 @@ main(int argc, char *argv[]) const char *opt = argv[i]; if (strncmp(opt, "-id", strlen(opt)) == 0) { /* note: the original also assumes this option on "sysinfo -" */ - printf("0x%.8lx 0x%.8lx\n", info.id[0], info.id[1]); + printf("0x%.8" B_PRIx32 " 0x%.8" B_PRIx32 "\n", info.id[0], + info.id[1]); } else if (strncmp(opt, "-cpu", strlen(opt)) == 0) { dump_cpus(&info); } else if (strncmp(opt, "-mem", strlen(opt)) == 0) { From a1a38e8aba0970729979f9dc0b3af72bd7b56e61 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 21:38:47 +0100 Subject: [PATCH 148/273] Retry a few times if opening keyboard fails in consoled. I'm using consoled at the moment without input_server having been run, so when it starts the input drivers will not have been loaded. Have to retry a few times with delays so that the input devices have a chance to appear. --- src/bin/consoled/consoled.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/bin/consoled/consoled.cpp b/src/bin/consoled/consoled.cpp index 3a1497fed9..1b38c04151 100644 --- a/src/bin/consoled/consoled.cpp +++ b/src/bin/consoled/consoled.cpp @@ -223,9 +223,18 @@ stop_keyboards(struct console* con) static struct keyboard* open_keyboards(int target, const char* start, struct keyboard* previous) { - DIR* dir = opendir(start); - if (dir == NULL) - return NULL; + // Wait for the directory to appear, if we're loaded early in boot + // it may take a while for it to appear while the drivers load. + DIR* dir; + int32 tries = 0; + while (true) { + dir = opendir(start); + if (dir != NULL) + break; + if(++tries == 10) + return NULL; + sleep(1); + } struct keyboard* keyboard = previous; From 666b46e2e3260e85ca6af913a73e75df9a24ab27 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 21:42:49 +0100 Subject: [PATCH 149/273] Added libbe, ICU and consoled to the image. The boot script now launches consoled instead if app_server does not exist, so there is now an interactive Bash prompt! libbe requires ICU, which is an optional package, so I've built the packages and they've been uploaded to haiku-files.org (thanks umccullough). --- build/jam/Haiku64Image | 19 +++++++++++++------ build/jam/OptionalBuildFeatures | 6 +++++- build/jam/OptionalPackages | 10 +++++++--- build/scripts/build_haiku_image | 3 +++ data/system/boot/Bootscript | 6 ++++++ 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index bc7bc4ade7..cb0311c51e 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -22,10 +22,11 @@ if $(HAIKU_ATA_STACK) = 1 { SYSTEM_BIN = "[" base64 basename bash cat chgrp chmod chown chroot cksum comm cp split cut date dd dircolors dirname du echo env expand expr factor false fmt fold getlimits groups head hostname id install join kill link - link ln logname ls md5sum mkdir mkfifo mktemp mv nl nohup nproc od paste - pathchk pr printenv printf ptx pwd readlink rm rmdir safemode seq sha1sum - shred shuf sleep sort split stat stty su sum sync tac tail tee test timeout - touch tr true truncate tsort tty unexpand uname uniq unlink wc whoami yes + ln locale logname ls md5sum mkdir mkfifo mktemp mv nl nohup nproc od paste + pathchk pr printenv printf ps ptx pwd readlink rm rmdir safemode seq + sha1sum shred shuf sleep sort split stat stty su sum sync sysinfo tac tail + tee test timeout touch tr true truncate tsort tty unexpand uname uniq + unlink wc whoami yes ; SYSTEM_APPS = ; @@ -34,7 +35,9 @@ SYSTEM_PREFERENCES = ; SYSTEM_DEMOS = ; -SYSTEM_LIBS = libroot.so ; +SYSTEM_LIBS = libbe.so libroot.so libroot-addon-icu.so + $(HAIKU_SHARED_LIBSTDC++) $(HAIKU_SHARED_LIBSUPC++) +; PRIVATE_SYSTEM_LIBS = ; @@ -83,7 +86,7 @@ AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ; # apps AddFilesToHaikuImage system : runtime_loader ; -AddFilesToHaikuImage system bin : $(SYSTEM_BIN) ; +AddFilesToHaikuImage system bin : $(SYSTEM_BIN) consoled ; AddFilesToHaikuImage system apps : $(SYSTEM_APPS) ; AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ; AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ; @@ -343,6 +346,10 @@ if $(HOST_RM_ATTRS_TARGET) { } else { AddVariableToScript $(script) : rmAttrs : rm ; } +if $(optionalPackageDescriptions) { + AddTargetVariableToScript $(script) : $(optionalPackageDescriptions) + : optionalPackageDescriptions ; +} # create the other scripts diff --git a/build/jam/OptionalBuildFeatures b/build/jam/OptionalBuildFeatures index cdd17eb11f..a77f820e47 100644 --- a/build/jam/OptionalBuildFeatures +++ b/build/jam/OptionalBuildFeatures @@ -69,12 +69,16 @@ if $(HAIKU_BUILD_FEATURE_SSL) { HAIKU_ICU_GCC_2_PACKAGE = icu-4.8.1-x86-gcc2-2011-11-02a.zip ; HAIKU_ICU_GCC_4_PACKAGE = icu-4.8.1-x86-gcc4-2011-11-02.zip ; HAIKU_ICU_PPC_PACKAGE = icu-4.8.1-ppc-2011-08-20.zip ; +HAIKU_ICU_X86_64_PACKAGE = icu-4.8.1.1-x86_64-2012-07-30.zip ; -if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 { +if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 || $(TARGET_ARCH) = x86_64 { local icu_package ; if $(TARGET_ARCH) = ppc { icu_package = $(HAIKU_ICU_PPC_PACKAGE) ; HAIKU_ICU_DEVEL_PACKAGE = icu-devel-4.8.1-ppc-2011-12-19.zip ; + } else if $(TARGET_ARCH) = x86_64 { + icu_package = $(HAIKU_ICU_X86_64_PACKAGE) ; + HAIKU_ICU_DEVEL_PACKAGE = icu-devel-4.8.1.1-x86_64-2012-07-30.zip ; } else if $(HAIKU_GCC_VERSION[1]) = 2 { icu_package = $(HAIKU_ICU_GCC_2_PACKAGE) ; HAIKU_ICU_DEVEL_PACKAGE = icu-devel-4.8.1.1-x86-gcc2-2011-12-20.zip ; diff --git a/build/jam/OptionalPackages b/build/jam/OptionalPackages index 6f27127193..b09ac11de2 100644 --- a/build/jam/OptionalPackages +++ b/build/jam/OptionalPackages @@ -1073,9 +1073,7 @@ if [ IsOptionalHaikuImagePackageAdded HGrep ] { # ICU if [ IsOptionalHaikuImagePackageAdded ICU ] { - if $(TARGET_ARCH) != x86 { - Echo "No optional package ICU available for $(TARGET_ARCH)" ; - } else { + if $(TARGET_ARCH) = x86 { if $(HAIKU_GCC_VERSION[1]) = 2 { # unzip gcc2 InstallOptionalHaikuImagePackage $(HAIKU_ICU_GCC_2_PACKAGE) @@ -1099,6 +1097,12 @@ if [ IsOptionalHaikuImagePackageAdded ICU ] { : system lib gcc2 ; } } + } else if $(TARGET_ARCH) = x86_64 { + InstallOptionalHaikuImagePackage $(HAIKU_ICU_X86_64_PACKAGE) + : $(baseURL)/$(HAIKU_ICU_X86_64_PACKAGE) + : system lib ; + } else { + Echo "No optional package ICU available for $(TARGET_ARCH)" ; } } diff --git a/build/scripts/build_haiku_image b/build/scripts/build_haiku_image index d6001f9d19..69100d9f0d 100755 --- a/build/scripts/build_haiku_image +++ b/build/scripts/build_haiku_image @@ -329,6 +329,8 @@ fi # ! updateOnly # add the concatenated copyrights as an attribute to AboutSystem if [ ! $updateOnly ]; then +# TODO x86_64: temporary hack, AboutSystem doesn't exist yet. +if [ -f $outputDir/objects/haiku/*/*/apps/aboutsystem/AboutSystem ]; then if [ -f $copyrightsFile ]; then copyrightAttrs=$tmpDir/copyrightAttrs $rmAttrs -f $copyrightAttrs @@ -337,6 +339,7 @@ if [ ! $updateOnly ]; then $copyAttrs ${sPrefix}$copyrightAttrs ${tPrefix}system/apps/AboutSystem fi fi +fi if [ $isCD ]; then # generate the attribute stores diff --git a/data/system/boot/Bootscript b/data/system/boot/Bootscript index 04a73bf6e6..e30521baf0 100644 --- a/data/system/boot/Bootscript +++ b/data/system/boot/Bootscript @@ -93,6 +93,12 @@ fi # Launch servers +# If app_server doesn't exist, just run consoled. +if [ ! -f "/boot/$SERVERS/app_server" ]; then + /bin/consoled + exit +fi + # We must wait for the app_server and registrar to be ready launch $SERVERS/registrar _roster_thread_ # launch registrar From 02dd3236d21fd322310a1f791bab69d7bc031434 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Mon, 30 Jul 2012 21:56:50 +0100 Subject: [PATCH 150/273] Better names for syscall/signal functions copied to the commpage. --- src/system/kernel/arch/x86/32/syscalls.cpp | 16 ++++++++-------- src/system/kernel/arch/x86/32/syscalls_asm.S | 12 ++++++------ src/system/kernel/arch/x86/64/signals.cpp | 8 ++++---- src/system/kernel/arch/x86/64/signals_asm.S | 6 +++--- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/system/kernel/arch/x86/32/syscalls.cpp b/src/system/kernel/arch/x86/32/syscalls.cpp index 3b3ffedba1..f0c9b7c1a0 100644 --- a/src/system/kernel/arch/x86/32/syscalls.cpp +++ b/src/system/kernel/arch/x86/32/syscalls.cpp @@ -18,10 +18,10 @@ // user syscall assembly stubs -extern "C" void _user_syscall_int(void); -extern unsigned int _user_syscall_int_end; -extern "C" void _user_syscall_sysenter(void); -extern unsigned int _user_syscall_sysenter_end; +extern "C" void x86_user_syscall_int(void); +extern unsigned int x86_user_syscall_int_end; +extern "C" void x86_user_syscall_sysenter(void); +extern unsigned int x86_user_syscall_sysenter_end; // sysenter handler extern "C" void x86_sysenter(); @@ -78,8 +78,8 @@ init_amd_syscall_registers(void* dummy, int cpuNum) void x86_initialize_syscall(void) { - void* syscallCode = (void *)&_user_syscall_int; - void* syscallCodeEnd = &_user_syscall_int_end; + void* syscallCode = (void *)&x86_user_syscall_int; + void* syscallCodeEnd = &x86_user_syscall_int_end; // check syscall if (all_cpus_have_feature(FEATURE_COMMON, IA32_FEATURE_SEP) @@ -89,8 +89,8 @@ x86_initialize_syscall(void) dprintf("initialize_commpage_syscall(): sysenter/sysexit supported\n"); // the code to be used in userland - syscallCode = (void *)&_user_syscall_sysenter; - syscallCodeEnd = &_user_syscall_sysenter_end; + syscallCode = (void *)&x86_user_syscall_sysenter; + syscallCodeEnd = &x86_user_syscall_sysenter_end; // tell all CPUs to init their sysenter/sysexit related registers call_all_cpus_sync(&init_intel_syscall_registers, NULL); diff --git a/src/system/kernel/arch/x86/32/syscalls_asm.S b/src/system/kernel/arch/x86/32/syscalls_asm.S index b4400caa3e..ef8b1e50c7 100644 --- a/src/system/kernel/arch/x86/32/syscalls_asm.S +++ b/src/system/kernel/arch/x86/32/syscalls_asm.S @@ -11,21 +11,21 @@ /* user space half of the syscall mechanism, to be copied into the commpage */ // int 99 fallback -FUNCTION(_user_syscall_int): +FUNCTION(x86_user_syscall_int): int $99 ret -FUNCTION_END(_user_syscall_int) -SYMBOL(_user_syscall_int_end): +FUNCTION_END(x86_user_syscall_int) +SYMBOL(x86_user_syscall_int_end): // Intel sysenter/sysexit -FUNCTION(_user_syscall_sysenter): +FUNCTION(x86_user_syscall_sysenter): // sysexit forces us to trash edx (-> eip) and ecx (-> esp), but they are // scratch registers anyway. We use ecx right away to store esp. movl %esp, %ecx sysenter ret -FUNCTION_END(_user_syscall_sysenter) -SYMBOL(_user_syscall_sysenter_end): +FUNCTION_END(x86_user_syscall_sysenter) +SYMBOL(x86_user_syscall_sysenter_end): diff --git a/src/system/kernel/arch/x86/64/signals.cpp b/src/system/kernel/arch/x86/64/signals.cpp index b8a29f1a39..947e76fbb7 100644 --- a/src/system/kernel/arch/x86/64/signals.cpp +++ b/src/system/kernel/arch/x86/64/signals.cpp @@ -16,15 +16,15 @@ #include -extern "C" void _user_signal_handler(void); -extern int _user_signal_handler_end; +extern "C" void x86_64_user_signal_handler(void); +extern int x86_64_user_signal_handler_end; void x86_initialize_commpage_signal_handler() { - void* handlerCode = (void*)&_user_signal_handler; - void* handlerCodeEnd = &_user_signal_handler_end; + void* handlerCode = (void*)&x86_64_user_signal_handler; + void* handlerCodeEnd = &x86_64_user_signal_handler_end; // Copy the signal handler code to the commpage. size_t len = (size_t)((addr_t)handlerCodeEnd - (addr_t)handlerCode); diff --git a/src/system/kernel/arch/x86/64/signals_asm.S b/src/system/kernel/arch/x86/64/signals_asm.S index 078a4c16af..5d85022707 100644 --- a/src/system/kernel/arch/x86/64/signals_asm.S +++ b/src/system/kernel/arch/x86/64/signals_asm.S @@ -14,7 +14,7 @@ // Userspace signal handler wrapper, copied to the commpage. -FUNCTION(_user_signal_handler): +FUNCTION(x86_64_user_signal_handler): push %rbp movq %rsp, %rbp @@ -52,5 +52,5 @@ FUNCTION(_user_signal_handler): leaq SIGNAL_FRAME_DATA_context(%r12), %rdx movq SIGNAL_FRAME_DATA_user_data(%r12), %rcx jmp .Lcall_handler -FUNCTION_END(_user_signal_handler) -SYMBOL(_user_signal_handler_end): +FUNCTION_END(x86_64_user_signal_handler) +SYMBOL(x86_64_user_signal_handler_end): From 3cd66dda5e623130a5ef7560da6851d421fd591e Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Tue, 31 Jul 2012 10:12:33 +0100 Subject: [PATCH 151/273] Fix CID 712419, 712420, 712421, 712422: Unintentional sign extension to 64 bits. --- src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp | 5 +++-- src/add-ons/kernel/file_systems/bfs/Inode.cpp | 5 +++-- src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp index e49b3b3910..61a7fbdf6e 100644 --- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp +++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp @@ -1990,8 +1990,9 @@ BlockAllocator::_CheckInodeBlocks(Inode* inode, const char* name) if (status != B_OK) return status; - int32 maxIndex = (indirect.Length() << fVolume->BlockShift()) - / sizeof(block_run); + int32 maxIndex = + ((uint32)indirect.Length() << fVolume->BlockShift()) + / sizeof(block_run); for (int32 index = 0; index < maxIndex; ) { block_run* runs = (block_run*)cachedDirect.SetTo( diff --git a/src/add-ons/kernel/file_systems/bfs/Inode.cpp b/src/add-ons/kernel/file_systems/bfs/Inode.cpp index 8e0c0f0dac..8abf77c3e9 100644 --- a/src/add-ons/kernel/file_systems/bfs/Inode.cpp +++ b/src/add-ons/kernel/file_systems/bfs/Inode.cpp @@ -1517,7 +1517,8 @@ Inode::FindBlockRun(off_t pos, block_run& run, off_t& offset) << fVolume->BlockShift(); if (runBlockEnd > pos) { run = data->direct[current]; - offset = runBlockEnd - (run.Length() << fVolume->BlockShift()); + offset = runBlockEnd + - ((uint32)run.Length() << fVolume->BlockShift()); return fVolume->ValidateBlockRun(run); } } @@ -1878,7 +1879,7 @@ Inode::_GrowStream(Transaction& transaction, off_t size) data->max_indirect_range = HOST_ENDIAN_TO_BFS_INT64( data->MaxIndirectRange() - + (run.Length() << fVolume->BlockShift())); + + ((uint32)run.Length() << fVolume->BlockShift())); data->size = HOST_ENDIAN_TO_BFS_INT64(blocksNeeded > 0 ? data->MaxIndirectRange() : size); continue; diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index fff1563cc1..ad9b88774d 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -527,7 +527,8 @@ bfs_get_file_map(fs_volume* _volume, fs_vnode* _node, off_t offset, size_t size, return status; vecs[index].offset = volume->ToOffset(run) + offset - fileOffset; - vecs[index].length = (run.Length() << blockShift) - offset + fileOffset; + vecs[index].length = ((uint32)run.Length() << blockShift) + - offset + fileOffset; // are we already done? if ((uint64)size <= (uint64)vecs[index].length From 8110732b0350b7a9bc72e831a56fbc874a113695 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 1 Aug 2012 11:00:35 +0100 Subject: [PATCH 152/273] Added some more binaries to the image. --- build/jam/Haiku64Image | 17 +++++++++++------ src/bin/catattr.cpp | 20 ++++++++++---------- src/bin/clockconfig.cpp | 2 +- src/bin/error.c | 2 +- src/bin/isvolume.cpp | 12 ++++++------ src/bin/listattr.cpp | 26 +++++++++++++------------- src/bin/listdev/listdev.c | 12 ++++++++---- src/bin/locale/collectcatkeys.cpp | 12 ++++++------ src/bin/locale/dumpcatalog.cpp | 11 ++++++----- src/bin/locale/linkcatkeys.cpp | 2 +- src/bin/mountvolume.cpp | 2 +- src/bin/ps.c | 29 ++++++++++++++++------------- 12 files changed, 80 insertions(+), 67 deletions(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index cb0311c51e..43741e0225 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -19,14 +19,19 @@ if $(HAIKU_ATA_STACK) = 1 { IDE_ONLY = "" ; } -SYSTEM_BIN = "[" base64 basename bash cat chgrp chmod chown chroot cksum comm - cp split cut date dd dircolors dirname du echo env expand expr factor false - fmt fold getlimits groups head hostname id install join kill link - ln locale logname ls md5sum mkdir mkfifo mktemp mv nl nohup nproc od paste - pathchk pr printenv printf ps ptx pwd readlink rm rmdir safemode seq +SYSTEM_BIN = "[" addattr base64 basename bash beep cal cat catattr chgrp chmod + chown chroot cksum clear clockconfig cmp collectcatkeys comm compress + copyattr cp csplit cut date dd diff diff3 dircolors dirname du + dumpcatalog echo eject env error expand expr factor false find finddir + fmt fold fortune gawk gzip gzexe getlimits groups head hostname id + install isvolume join kernel_debugger kill less lessecho lesskey link + linkcatkeys listdev ln locale locate logger logname ls md5sum mkdir mkfifo + mktemp mount mountvolume mv nl nohup nproc od paste patch pathchk pr + printenv printf ps ptx pwd readlink rm rmattr rmdir safemode sdiff seq sha1sum shred shuf sleep sort split stat stty su sum sync sysinfo tac tail tee test timeout touch tr true truncate tsort tty unexpand uname uniq - unlink wc whoami yes + unlink unmount unzip updatedb waitfor wc whoami xargs xres yes + zdiff zforce zgrep zip zipcloak zipgrep zipnote zipsplit zmore znew ; SYSTEM_APPS = ; diff --git a/src/bin/catattr.cpp b/src/bin/catattr.cpp index 568c0031cc..eab474f8e8 100644 --- a/src/bin/catattr.cpp +++ b/src/bin/catattr.cpp @@ -43,7 +43,7 @@ dumpRawData(const char *buffer, size_t size) while (dumpPosition < size) { // Position for this line - printf("0x%06lx: ", dumpPosition); + printf("0x%06" B_PRIx32 ": ", dumpPosition); // Print the bytes in form of hexadecimal numbers for (uint32 i = 0; i < kChunkSize; i++) { @@ -88,7 +88,7 @@ type_to_string(uint32 type) sprintf(buffer, "'%c%c%c%c'", value[0], value[1], value[2], value[3]); } else - sprintf(buffer, "0x%08lx", type); + sprintf(buffer, "0x%08" B_PRIx32, type); return buffer; } @@ -218,28 +218,28 @@ catAttr(const char *attribute, const char *fileName, bool keepRaw, switch (info.type) { case B_INT8_TYPE: - printf("%d\n", *((int8*)buffer)); + printf("%" B_PRId8 "\n", *((int8*)buffer)); break; case B_UINT8_TYPE: - printf("%u\n", *((uint8*)buffer)); + printf("%" B_PRIu8 "\n", *((uint8*)buffer)); break; case B_INT16_TYPE: - printf("%d\n", *((int16*)buffer)); + printf("%" B_PRId16 "\n", *((int16*)buffer)); break; case B_UINT16_TYPE: - printf("%u\n", *((uint16*)buffer)); + printf("%" B_PRIu16 "\n", *((uint16*)buffer)); break; case B_INT32_TYPE: - printf("%ld\n", *((int32*)buffer)); + printf("%" B_PRId32 "\n", *((int32*)buffer)); break; case B_UINT32_TYPE: - printf("%lu\n", *((uint32*)buffer)); + printf("%" B_PRIu32 "\n", *((uint32*)buffer)); break; case B_INT64_TYPE: - printf("%Ld\n", *((int64*)buffer)); + printf("%" B_PRId64 "\n", *((int64*)buffer)); break; case B_UINT64_TYPE: - printf("%Lu\n", *((uint64*)buffer)); + printf("%" B_PRIu64 "\n", *((uint64*)buffer)); break; case B_FLOAT_TYPE: printf("%f\n", *((float*)buffer)); diff --git a/src/bin/clockconfig.cpp b/src/bin/clockconfig.cpp index 8acb56afc9..78c73520f7 100644 --- a/src/bin/clockconfig.cpp +++ b/src/bin/clockconfig.cpp @@ -73,7 +73,7 @@ setTimeZoneOffset(BPath path) _kern_set_timezone(timeZoneOffset, timeZoneID.String(), timeZoneID.Length()); - printf("timezone is %s, offset is %ld seconds from GMT.\n", + printf("timezone is %s, offset is %" B_PRId32 " seconds from GMT.\n", timeZoneID.String(), timeZoneOffset); } diff --git a/src/bin/error.c b/src/bin/error.c index ff2b98c8d5..c18a71e237 100644 --- a/src/bin/error.c +++ b/src/bin/error.c @@ -320,7 +320,7 @@ print_error(char *number) error = p->value; } - printf("0x%lx: %s\n", error, strerror(error)); + printf("0x%" B_PRIx32 ": %s\n", error, strerror(error)); } diff --git a/src/bin/isvolume.cpp b/src/bin/isvolume.cpp index 0d4c0b9455..a7a8b89103 100644 --- a/src/bin/isvolume.cpp +++ b/src/bin/isvolume.cpp @@ -93,8 +93,8 @@ main(int argc, char** argv) BVolume volume(volumeDevice); status_t ret = volume.InitCheck(); if (ret != B_OK) { - fprintf(stderr, "%s: failed to get BVolume for device %ld: %s\n", - argv[0], volumeDevice, strerror(ret)); + fprintf(stderr, "%s: failed to get BVolume for device %" B_PRIdDEV + ": %s\n", argv[0], volumeDevice, strerror(ret)); return 1; } @@ -103,8 +103,8 @@ main(int argc, char** argv) BPartition* partition; ret = roster.FindPartitionByVolume(volume, &diskDevice, &partition); if (ret != B_OK) { - fprintf(stderr, "%s: failed to get partition for device %ld: %s\n", - argv[0], volumeDevice, strerror(ret)); + fprintf(stderr, "%s: failed to get partition for device %" B_PRIdDEV + ": %s\n", argv[0], volumeDevice, strerror(ret)); return 1; } // check this option directly and not via fs_stat_dev() @@ -122,8 +122,8 @@ main(int argc, char** argv) return 0; } else { - fprintf(stderr, "%s: can't get information about dev_t: %ld\n", - argv[0], volumeDevice); + fprintf(stderr, "%s: can't get information about dev_t: %" B_PRIdDEV + "\n", argv[0], volumeDevice); return 1; } } diff --git a/src/bin/listattr.cpp b/src/bin/listattr.cpp index 77ea615dd8..13e4010828 100644 --- a/src/bin/listattr.cpp +++ b/src/bin/listattr.cpp @@ -29,7 +29,7 @@ dump_raw_data(const char *buffer, size_t size) while (dumpPosition < size) { // Position for this line - printf("\t%04lx: ", dumpPosition); + printf("\t%04" B_PRIx32 ": ", dumpPosition); // Print the bytes in form of hexadecimal numbers for (uint32 i = 0; i < kChunkSize; i++) { @@ -72,35 +72,35 @@ show_attr_contents(BNode& node, const char* attribute, const attr_info& info) char buffer[kLimit]; ssize_t bytesRead = node.ReadAttr(attribute, info.type, 0, buffer, size); if (bytesRead != size) { - fprintf(stderr, "Could only read %lld bytes from attribute!\n", + fprintf(stderr, "Could only read %" B_PRIdOFF " bytes from attribute!\n", size); return; } switch (info.type) { case B_INT8_TYPE: - printf("%d\n", *((int8 *)buffer)); + printf("%" B_PRId8 "\n", *((int8 *)buffer)); break; case B_UINT8_TYPE: - printf("%u\n", *((uint8 *)buffer)); + printf("%" B_PRIu8 "\n", *((uint8 *)buffer)); break; case B_INT16_TYPE: - printf("%d\n", *((int16 *)buffer)); + printf("%" B_PRId16 "\n", *((int16 *)buffer)); break; case B_UINT16_TYPE: - printf("%u\n", *((uint16 *)buffer)); + printf("%" B_PRIu16 "\n", *((uint16 *)buffer)); break; case B_INT32_TYPE: - printf("%ld\n", *((int32 *)buffer)); + printf("%" B_PRId32 "\n", *((int32 *)buffer)); break; case B_UINT32_TYPE: - printf("%lu\n", *((uint32 *)buffer)); + printf("%" B_PRIu32 "\n", *((uint32 *)buffer)); break; case B_INT64_TYPE: - printf("%lld\n", *((int64 *)buffer)); + printf("%" B_PRId64 "\n", *((int64 *)buffer)); break; case B_UINT64_TYPE: - printf("%llu\n", *((uint64 *)buffer)); + printf("%" B_PRIu64 "\n", *((uint64 *)buffer)); break; case B_FLOAT_TYPE: printf("%f\n", *((float *)buffer)); @@ -198,7 +198,7 @@ get_type(type_code type) sprintf(buffer, "'%c%c%c%c'", value[0], value[1], value[2], value[3]); } else - sprintf(buffer, "0x%08lx", type); + sprintf(buffer, "0x%08" B_PRIx32, type); return buffer; } @@ -262,7 +262,7 @@ main(int argc, char *argv[]) status = node.GetAttrInfo(name, &attrInfo); if (status >= B_OK) { printf("%*s", kTypeWidth, get_type(attrInfo.type)); - printf("% *Li ", kSizeWidth, attrInfo.size); + printf("% *" B_PRId64 " ", kSizeWidth, attrInfo.size); printf("\"%s\"", name); if (printContents) { @@ -283,6 +283,6 @@ main(int argc, char *argv[]) } } - printf("\n%Ld bytes total in attributes.\n", total); + printf("\n%" B_PRId64 " bytes total in attributes.\n", total); return 0; } diff --git a/src/bin/listdev/listdev.c b/src/bin/listdev/listdev.c index f582d0fa5d..77cc02a532 100644 --- a/src/bin/listdev/listdev.c +++ b/src/bin/listdev/listdev.c @@ -87,16 +87,20 @@ dump_attribute(struct device_attr_info *attr, int32 level) printf("string : \"%s\"", attr->value.string); break; case B_UINT8_TYPE: - printf("uint8 : %u (%#x)", attr->value.ui8, attr->value.ui8); + printf("uint8 : %" B_PRIu8 " (%#" B_PRIx8 ")", attr->value.ui8, + attr->value.ui8); break; case B_UINT16_TYPE: - printf("uint16 : %u (%#x)", attr->value.ui16, attr->value.ui16); + printf("uint16 : %" B_PRIu16 " (%#" B_PRIx16 ")", attr->value.ui16, + attr->value.ui16); break; case B_UINT32_TYPE: - printf("uint32 : %lu (%#lx)", attr->value.ui32, attr->value.ui32); + printf("uint32 : %" B_PRIu32 " (%#" B_PRIx32 ")", attr->value.ui32, + attr->value.ui32); break; case B_UINT64_TYPE: - printf("uint64 : %Lu (%#Lx)", attr->value.ui64, attr->value.ui64); + printf("uint64 : %" B_PRIu64 " (%#" B_PRIx64 ")", attr->value.ui64, + attr->value.ui64); break; default: printf("raw data"); diff --git a/src/bin/locale/collectcatkeys.cpp b/src/bin/locale/collectcatkeys.cpp index 06156c8d6c..e8ded99946 100644 --- a/src/bin/locale/collectcatkeys.cpp +++ b/src/bin/locale/collectcatkeys.cpp @@ -184,11 +184,11 @@ collectAllCatalogKeys(BString& inputStr) if (fetchKey(in)) { if (haveID) { if (showKeys) - printf("CatKey(%ld)\n", id); + printf("CatKey(%" B_PRId32 ")\n", id); res = catalog->SetString(id, ""); if (res != B_OK) { - fprintf(stderr, "couldn't add key %ld - error: %s\n", - id, strerror(res)); + fprintf(stderr, "couldn't add key %" B_PRId32 " - error: " + "%s\n", id, strerror(res)); exit(-1); } } else { @@ -285,8 +285,8 @@ main(int argc, char **argv) char *buf = inputStr.LockBuffer(sz); off_t rsz = inFile.Read(buf, sz); if (rsz < sz) { - fprintf(stderr, "couldn't read %Ld bytes from %s (got only %Ld)\n", - sz, inputFile, rsz); + fprintf(stderr, "couldn't read %" B_PRId64 " bytes from %s (got " + "only %" B_PRId64 ")\n", sz, inputFile, rsz); exit(-1); } inputStr.UnlockBuffer(rsz); @@ -301,7 +301,7 @@ main(int argc, char **argv) if (showSummary) { int32 count = catalog->CountItems(); if (count) - fprintf(stderr, "%ld key%s found and written to %s\n", + fprintf(stderr, "%" B_PRId32 " key%s found and written to %s\n", count, (count==1 ? "": "s"), outputFile.String()); else fprintf(stderr, "no keys found\n"); diff --git a/src/bin/locale/dumpcatalog.cpp b/src/bin/locale/dumpcatalog.cpp index b1f58b6054..d90f790bdc 100644 --- a/src/bin/locale/dumpcatalog.cpp +++ b/src/bin/locale/dumpcatalog.cpp @@ -64,15 +64,16 @@ main(int argc, char **argv) while (!walker.AtEnd()) { const CatKey &key(walker.GetKey()); key.GetStringParts(&str, &ctx, &cmt); - printf("Hash:\t\t%lu\nKey:\t\t<%s:%s:%s>\nTranslation:\t%s\n-----\n", - key.fHashVal, str.String(), ctx.String(), cmt.String(), + printf("Hash:\t\t%" B_PRIu32 "\nKey:\t\t<%s:%s:%s>\nTranslation:\t%s\n" + "-----\n", key.fHashVal, str.String(), ctx.String(), cmt.String(), walker.GetValue()); walker.Next(); } int32 count = inputCatalog.CountItems(); - if (count) - fprintf(stderr, "%ld entr%s dumped\n", count, (count==1 ? "y": "ies")); - else + if (count) { + fprintf(stderr, "%" B_PRId32 " entr%s dumped\n", count, + (count==1 ? "y": "ies")); + } else fprintf(stderr, "no entries found\n"); return res; } diff --git a/src/bin/locale/linkcatkeys.cpp b/src/bin/locale/linkcatkeys.cpp index 0fe8ac9b2f..be81f5a948 100644 --- a/src/bin/locale/linkcatkeys.cpp +++ b/src/bin/locale/linkcatkeys.cpp @@ -180,7 +180,7 @@ main(int argc, char **argv) if (showSummary) { int32 count = targetCatalog.CountItems(); if (count) { - fprintf(stderr, "%ld key%s found and written to %s\n", + fprintf(stderr, "%" B_PRId32 " key%s found and written to %s\n", count, (count==1 ? "": "s"), outputFile.String()); } else fprintf(stderr, "no keys found\n"); diff --git a/src/bin/mountvolume.cpp b/src/bin/mountvolume.cpp index d3c2be3378..b9bd217749 100644 --- a/src/bin/mountvolume.cpp +++ b/src/bin/mountvolume.cpp @@ -99,7 +99,7 @@ size_string(int64 size) static char string[64]; if (size < 1024) - sprintf(string, "%Ld", size); + sprintf(string, "%" B_PRId64, size); else { const char* units[] = {"K", "M", "G", NULL}; int32 i = -1; diff --git a/src/bin/ps.c b/src/bin/ps.c index 92416ceb96..078a636008 100644 --- a/src/bin/ps.c +++ b/src/bin/ps.c @@ -28,8 +28,8 @@ printTeamInfo(team_info *teamInfo, bool printHeader) printf("%-50s %5s %8s %4s %4s\n", "Team", "Id", "#Threads", "Gid", \ "Uid"); - printf("%-50s %5ld %8ld %4d %4d\n", teamInfo->args, teamInfo->team, - teamInfo->thread_count, teamInfo->uid, teamInfo->gid); + printf("%-50s %5" B_PRId32 " %8" B_PRId32 " %4d %4d\n", teamInfo->args, + teamInfo->team, teamInfo->thread_count, teamInfo->uid, teamInfo->gid); } @@ -37,7 +37,7 @@ static void printTeamThreads(team_info *teamInfo, bool printSemaphoreInfo) { char *threadState; - uint32 threadCookie = 0; + int32 threadCookie = 0; sem_info semaphoreInfo; thread_info threadInfo; @@ -51,18 +51,21 @@ printTeamThreads(team_info *teamInfo, bool printSemaphoreInfo) else threadState = sStates[threadInfo.state - 1]; - printf("%-37s %5ld %8s %4ld %8llu %8llu ", - threadInfo.name, threadInfo.thread, threadState, + printf("%-37s %5" B_PRId32 " %8s %4" B_PRId32 " %8" B_PRIu64 " %8" + B_PRId64 " ", threadInfo.name, threadInfo.thread, threadState, threadInfo.priority, (threadInfo.user_time / 1000), (threadInfo.kernel_time / 1000)); if (printSemaphoreInfo) { if (threadInfo.state == B_THREAD_WAITING && threadInfo.sem != -1) { status_t status = get_sem_info(threadInfo.sem, &semaphoreInfo); - if (status == B_OK) - printf("%s(%ld)\n", semaphoreInfo.name, semaphoreInfo.sem); - else - printf("%s(%ld)\n", strerror(status), threadInfo.sem); + if (status == B_OK) { + printf("%s(%" B_PRId32 ")\n", semaphoreInfo.name, + semaphoreInfo.sem); + } else { + printf("%s(%" B_PRId32 ")\n", strerror(status), + threadInfo.sem); + } } else puts(""); } else @@ -74,7 +77,7 @@ int main(int argc, char **argv) { team_info teamInfo; - uint32 teamCookie = 0; + int32 teamCookie = 0; system_info systemInfo; bool printSystemInfo = false; bool printThreads = false; @@ -153,13 +156,13 @@ main(int argc, char **argv) // system stats get_system_info(&systemInfo); printf("\nSystem Info\n"); - printf("%luk (%lu bytes) total memory\n", + printf("%" B_PRIu32 "k (%" B_PRIu32 " bytes) total memory\n", (systemInfo.max_pages * B_PAGE_SIZE / 1024), (systemInfo.max_pages * B_PAGE_SIZE)); - printf("%luk (%lu bytes) currently committed\n", + printf("%" B_PRIu32 "k (%" B_PRIu32 " bytes) currently committed\n", (systemInfo.used_pages * B_PAGE_SIZE / 1024), (systemInfo.used_pages * B_PAGE_SIZE)); - printf("%luk (%lu bytes) currently available\n", + printf("%" B_PRIu32 "k (%" B_PRIu32 " bytes) currently available\n", (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE / 1024, (systemInfo.max_pages - systemInfo.used_pages) * B_PAGE_SIZE); printf("%2.1f%% memory utilisation\n", From 9a5503d01c41c7afc680c30256fba28700fc8b60 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 1 Aug 2012 11:13:14 +0100 Subject: [PATCH 153/273] Different uname machine type for x86_64. * Added B_64_BIT_PC_PLATFORM platform type. * Return "x86_64" as the machine type for that platform in uname. --- headers/os/kernel/OS.h | 3 ++- src/system/kernel/arch/x86/arch_system_info.cpp | 4 ++++ src/system/libroot/posix/sys/uname.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/headers/os/kernel/OS.h b/headers/os/kernel/OS.h index 6fc6a3badd..d5441da4d2 100644 --- a/headers/os/kernel/OS.h +++ b/headers/os/kernel/OS.h @@ -713,7 +713,8 @@ typedef enum platform_types { B_MK_61_PLATFORM, B_NINTENDO_64_PLATFORM, B_AMIGA_PLATFORM, - B_ATARI_PLATFORM + B_ATARI_PLATFORM, + B_64_BIT_PC_PLATFORM } platform_type; typedef struct { diff --git a/src/system/kernel/arch/x86/arch_system_info.cpp b/src/system/kernel/arch/x86/arch_system_info.cpp index 8789dca0f4..a1423ffaa7 100644 --- a/src/system/kernel/arch/x86/arch_system_info.cpp +++ b/src/system/kernel/arch/x86/arch_system_info.cpp @@ -68,7 +68,11 @@ arch_get_system_info(system_info *info, size_t size) // - various cpu_info info->cpu_clock_speed = sCpuClockSpeed; // - bus_clock_speed +#ifdef __x86_64__ + info->platform_type = B_64_BIT_PC_PLATFORM; +#else info->platform_type = B_AT_CLONE_PLATFORM; +#endif // ToDo: clock speeds could be retrieved via SMBIOS/DMI return B_OK; diff --git a/src/system/libroot/posix/sys/uname.c b/src/system/libroot/posix/sys/uname.c index 8fe5be1d3c..120a95157d 100644 --- a/src/system/libroot/posix/sys/uname.c +++ b/src/system/libroot/posix/sys/uname.c @@ -55,6 +55,9 @@ uname(struct utsname *info) case B_AT_CLONE_PLATFORM: platform = "BePC"; break; + case B_64_BIT_PC_PLATFORM: + platform = "x86_64"; + break; default: platform = "unknown"; break; From b77772725ccf08904ed1ed8e0e28500868093ef4 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Wed, 1 Aug 2012 11:46:44 +0100 Subject: [PATCH 154/273] Changed x86_64 toolchain target to x86_64-unknown-haiku. --- configure | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/configure b/configure index a80eed5eff..b11cf98a81 100755 --- a/configure +++ b/configure @@ -401,7 +401,7 @@ while [ $# -gt 0 ] ; do buildCrossToolsScript="${buildCrossToolsScript}_gcc4" case "$2" in x86) HAIKU_GCC_MACHINE=i586-pc-haiku;; - x86_64) HAIKU_GCC_MACHINE=x86_64-pc-haiku; targetArch=x86_64;; + x86_64) HAIKU_GCC_MACHINE=x86_64-unknown-haiku; targetArch=x86_64;; ppc) HAIKU_GCC_MACHINE=powerpc-apple-haiku; targetArch=ppc;; m68k) HAIKU_GCC_MACHINE=m68k-unknown-haiku; targetArch=m68k;; arm) HAIKU_GCC_MACHINE=arm-unknown-haiku; targetArch=arm;; @@ -511,6 +511,13 @@ if [ -n "$crossToolsPrefix" ]; then get_build_tool_path LD ld get_build_tool_path OBJCOPY objcopy get_build_tool_path RANLIB ranlib +fi + +# prepare gcc settings +standard_gcc_settings + +# cross tools for gcc4 builds +if [ -n "$crossToolsPrefix" ]; then case $HAIKU_GCC_RAW_VERSION in 4.*) get_build_tool_path ELFEDIT elfedit @@ -518,9 +525,6 @@ if [ -n "$crossToolsPrefix" ]; then esac fi -# prepare gcc settings -standard_gcc_settings - # check whether the Haiku compiler really targets Haiku or BeOS case "$HAIKU_GCC_MACHINE" in *-*-haiku) ;; From d93ed095640345495ace3b653ea87b66815c7c81 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 2 Aug 2012 09:32:33 +0100 Subject: [PATCH 155/273] Improved safety for user memory accesses. * Changed IS_USER_ADDRESS to check an address using USER_BASE and USER_SIZE, rather than just !IS_KERNEL_ADDRESS. The old check would allow user buffers to point into the physical memory map area. * Added an unmapped hole at the end of the bottom half of the address space which catches buffers that cross into the uncanonical address region. This also removes the need to check for uncanonical return addresses in the syscall handler, it is no longer possible for the return address to be uncanonical under normal circumstances. All cases in which the return address might be changed by the kernel are still handled via the IRET path. --- headers/private/kernel/arch/arm/arch_kernel.h | 4 ++-- headers/private/kernel/arch/m68k/arch_kernel.h | 4 ++-- headers/private/kernel/arch/mipsel/arch_kernel.h | 4 ++-- headers/private/kernel/arch/ppc/arch_kernel.h | 4 ++-- headers/private/kernel/arch/x86/arch_kernel.h | 15 +++++++++------ headers/private/kernel/kernel.h | 9 ++++++++- src/system/kernel/arch/x86/64/interrupts.S | 13 ------------- 7 files changed, 25 insertions(+), 28 deletions(-) diff --git a/headers/private/kernel/arch/arm/arch_kernel.h b/headers/private/kernel/arch/arm/arch_kernel.h index af0a9e26f7..44a05e74a6 100644 --- a/headers/private/kernel/arch/arm/arch_kernel.h +++ b/headers/private/kernel/arch/arm/arch_kernel.h @@ -23,10 +23,10 @@ #define USER_BASE 0x100000 #define USER_BASE_ANY USER_BASE #define USER_SIZE (0x80000000 - (0x10000 + 0x100000)) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #endif /* _KERNEL_ARCH_ARM_KERNEL_H */ diff --git a/headers/private/kernel/arch/m68k/arch_kernel.h b/headers/private/kernel/arch/m68k/arch_kernel.h index 85e9168d33..7f9806999a 100644 --- a/headers/private/kernel/arch/m68k/arch_kernel.h +++ b/headers/private/kernel/arch/m68k/arch_kernel.h @@ -23,10 +23,10 @@ #define USER_BASE 0x100000 #define USER_BASE_ANY USER_BASE #define USER_SIZE (0x80000000 - (0x10000 + 0x100000)) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #endif /* _KERNEL_ARCH_M68K_KERNEL_H */ diff --git a/headers/private/kernel/arch/mipsel/arch_kernel.h b/headers/private/kernel/arch/mipsel/arch_kernel.h index 6eea165c55..42f3c8fbaf 100644 --- a/headers/private/kernel/arch/mipsel/arch_kernel.h +++ b/headers/private/kernel/arch/mipsel/arch_kernel.h @@ -26,11 +26,11 @@ #define USER_BASE 0x100000 #define USER_BASE_ANY USER_BASE #define USER_SIZE (0x80000000 - (0x10000 + 0x100000)) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #endif /* _KERNEL_ARCH_MIPSEL_KERNEL_H */ diff --git a/headers/private/kernel/arch/ppc/arch_kernel.h b/headers/private/kernel/arch/ppc/arch_kernel.h index 3886034f11..c7d448084b 100644 --- a/headers/private/kernel/arch/ppc/arch_kernel.h +++ b/headers/private/kernel/arch/ppc/arch_kernel.h @@ -23,10 +23,10 @@ #define USER_BASE 0x100000 #define USER_BASE_ANY USER_BASE #define USER_SIZE (0x80000000 - (0x10000 + 0x100000)) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #endif /* _KERNEL_ARCH_PPC_KERNEL_H */ diff --git a/headers/private/kernel/arch/x86/arch_kernel.h b/headers/private/kernel/arch/x86/arch_kernel.h index 87e676b58d..366852526d 100644 --- a/headers/private/kernel/arch/x86/arch_kernel.h +++ b/headers/private/kernel/arch/x86/arch_kernel.h @@ -40,14 +40,17 @@ #define KERNEL_PMAP_SIZE 0x8000000000 // Userspace address space layout. +// There is a 2MB hole just before the end of the bottom half of the address +// space. This means that if userland passes in a buffer that crosses into the +// uncanonical address region, it will be caught through a page fault. #define USER_BASE 0x0 #define USER_BASE_ANY 0x100000 -#define USER_SIZE 0x800000000000 -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_SIZE (0x800000000000 - 0x200000) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x7fffefff0000 #define USER_STACK_REGION 0x7ffff0000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #else // __x86_64__ @@ -68,14 +71,14 @@ * TODO: introduce the 1Mb lower barrier again - it's only used for vm86 mode, * and this should be moved into the kernel (and address space) completely. */ -#define USER_BASE 0x00 +#define USER_BASE 0x0 #define USER_BASE_ANY 0x100000 #define USER_SIZE (KERNEL_BASE - 0x10000) -#define USER_TOP (USER_BASE + USER_SIZE) +#define USER_TOP (USER_BASE + (USER_SIZE - 1)) #define KERNEL_USER_DATA_BASE 0x6fff0000 #define USER_STACK_REGION 0x70000000 -#define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) +#define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1) #endif // __x86_64__ diff --git a/headers/private/kernel/kernel.h b/headers/private/kernel/kernel.h index ec5a166f56..a5c01e37ea 100644 --- a/headers/private/kernel/kernel.h +++ b/headers/private/kernel/kernel.h @@ -31,7 +31,14 @@ #endif // Buffers passed in from user-space shouldn't point into the kernel. -#define IS_USER_ADDRESS(x) (!IS_KERNEL_ADDRESS(x)) +#if USER_BASE == 0 +# define IS_USER_ADDRESS(x) ((addr_t)(x) <= USER_TOP) +#elif USER_TOP == __HAIKU_ADDR_MAX +# define IS_USER_ADDRESS(x) ((addr_t)(x) >= USER_BASE) +#else +# define IS_USER_ADDRESS(x) \ + ((addr_t)(x) >= USER_BASE && (addr_t)(x) <= USER_TOP) +#endif #define DEBUG_KERNEL_STACKS // Note, debugging kernel stacks doesn't really work yet. Since the diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index acc82a083b..a74b7b4633 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -393,19 +393,6 @@ FUNCTION(x86_64_syscall_entry): cmpq $SYSCALL_RESTORE_SIGNAL_FRAME, %r14 je .Liret - // If the return address is not canonical, return using the IRET path. - // On Intel's implementation of SYSRET, the canonical address check for the - // return address is performed before the switch to user mode, so a fault - // for a non-canonical address will be triggered in kernel mode. However, by - // then we will have switched onto the user stack meaning the kernel could - // be tricked into executing with the user RSP. Using IRET will handle - // non-canonical addresses properly. - movq IFRAME_user_sp(%rsp), %rax - sarq $47, %rax - incl %eax - cmpl $1, %eax - ja .Liret - // Restore the iframe and RCX/R11 for SYSRET. RESTORE_IFRAME() pop %rcx From 50cedfd5b01a968c2da00bfd014360b24a3aac66 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Thu, 2 Aug 2012 10:45:42 +0100 Subject: [PATCH 156/273] Build registrar for x86_64. --- build/jam/Haiku64Image | 18 +++++++++--------- data/system/boot/Bootscript | 6 +++--- .../registrar/AuthenticationManager.cpp | 3 ++- src/servers/registrar/EventQueue.cpp | 4 ++-- src/servers/registrar/MIMEManager.cpp | 6 +++--- src/servers/registrar/MessagingService.cpp | 13 +++++++------ src/servers/registrar/RecentEntries.cpp | 15 ++++++++------- src/servers/registrar/mime/AssociatedTypes.cpp | 5 +++-- src/servers/registrar/mime/InstalledTypes.cpp | 6 ++++-- .../registrar/mime/MimeUpdateThread.cpp | 4 ++-- .../registrar/mime/RegistrarThreadManager.cpp | 5 +++-- src/servers/registrar/mime/SnifferRules.cpp | 6 ++++-- 12 files changed, 50 insertions(+), 41 deletions(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 43741e0225..ba5c32f4bc 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -46,7 +46,7 @@ SYSTEM_LIBS = libbe.so libroot.so libroot-addon-icu.so PRIVATE_SYSTEM_LIBS = ; -SYSTEM_SERVERS = ; +SYSTEM_SERVERS = registrar ; SYSTEM_ADD_ONS_BUS_MANAGERS = $(ATA_ONLY)ata pci ps2 isa scsi config_manager ; SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; @@ -97,14 +97,14 @@ AddFilesToHaikuImage system preferences : $(SYSTEM_PREFERENCES) ; AddFilesToHaikuImage system demos : $(SYSTEM_DEMOS) ; AddSymlinkToHaikuImage system bin : bash : sh ; -#AddSymlinkToHaikuImage system bin : less : more ; -#AddSymlinkToHaikuImage system bin : gzip : gunzip ; -#AddSymlinkToHaikuImage system bin : gzip : zcat ; -#AddSymlinkToHaikuImage system bin : zdiff : zcmp ; -#AddSymlinkToHaikuImage system bin : unzip : zipinfo ; -#AddSymlinkToHaikuImage system bin : gawk : awk ; -#AddSymlinkToHaikuImage system bin : grep : egrep ; -#AddSymlinkToHaikuImage system bin : grep : fgrep ; +AddSymlinkToHaikuImage system bin : less : more ; +AddSymlinkToHaikuImage system bin : gzip : gunzip ; +AddSymlinkToHaikuImage system bin : gzip : zcat ; +AddSymlinkToHaikuImage system bin : zdiff : zcmp ; +AddSymlinkToHaikuImage system bin : unzip : zipinfo ; +AddSymlinkToHaikuImage system bin : gawk : awk ; +AddSymlinkToHaikuImage system bin : grep : egrep ; +AddSymlinkToHaikuImage system bin : grep : fgrep ; # scripts and data files diff --git a/data/system/boot/Bootscript b/data/system/boot/Bootscript index e30521baf0..3a52cb2ea2 100644 --- a/data/system/boot/Bootscript +++ b/data/system/boot/Bootscript @@ -93,15 +93,15 @@ fi # Launch servers +# We must wait for the app_server and registrar to be ready +launch $SERVERS/registrar _roster_thread_ # launch registrar + # If app_server doesn't exist, just run consoled. if [ ! -f "/boot/$SERVERS/app_server" ]; then /bin/consoled exit fi -# We must wait for the app_server and registrar to be ready -launch $SERVERS/registrar _roster_thread_ # launch registrar - launch $SERVERS/debug_server # launch debug_server # Init Network diff --git a/src/servers/registrar/AuthenticationManager.cpp b/src/servers/registrar/AuthenticationManager.cpp index d5a2c7632b..d841ad7632 100644 --- a/src/servers/registrar/AuthenticationManager.cpp +++ b/src/servers/registrar/AuthenticationManager.cpp @@ -975,7 +975,8 @@ AuthenticationManager::_RequestThread() debug_printf("B_REG_UPDATE_GROUP done: currently unsupported!\n"); break; default: - debug_printf("REG: invalid message: %lu\n", message.What()); + debug_printf("REG: invalid message: %" B_PRIu32 "\n", + message.What()); } } diff --git a/src/servers/registrar/EventQueue.cpp b/src/servers/registrar/EventQueue.cpp index f9e31c3817..cdb46b9064 100644 --- a/src/servers/registrar/EventQueue.cpp +++ b/src/servers/registrar/EventQueue.cpp @@ -114,7 +114,7 @@ EventQueue::EventQueue(const char *name) EventQueue::~EventQueue() { Die(); - while (Event *event = (Event*)fEvents.RemoveItem(0L)) { + while (Event *event = (Event*)fEvents.RemoveItem((int32)0)) { if (event->IsAutoDelete()) delete event; } @@ -347,7 +347,7 @@ EventQueue::_EventLooper() // do events, that are supposed to go off while (!fTerminating && Lock() && !fEvents.IsEmpty() && system_time() >= _EventAt(0)->Time()) { - Event *event = (Event*)fEvents.RemoveItem(0L); + Event *event = (Event*)fEvents.RemoveItem((int32)0); Unlock(); bool autoDeleteEvent = event->IsAutoDelete(); bool deleteEvent = event->Do(this) || autoDeleteEvent; diff --git a/src/servers/registrar/MIMEManager.cpp b/src/servers/registrar/MIMEManager.cpp index c5a8ff19ea..e357fb9e4e 100644 --- a/src/servers/registrar/MIMEManager.cpp +++ b/src/servers/registrar/MIMEManager.cpp @@ -181,7 +181,7 @@ MIMEManager::MessageReceived(BMessage *message) err = fDatabase.GuessMimeType(&ref, &str); else if (err == B_NAME_NOT_FOUND) { const void *data; - int32 dataSize; + ssize_t dataSize; err = message->FindData("data", B_RAW_TYPE, &data, &dataSize); if (!err) @@ -290,8 +290,8 @@ MIMEManager::MessageReceived(BMessage *message) } default: - printf("MIMEMan: msg->what == %lx (%.4s)\n", message->what, - (char*)&(message->what)); + printf("MIMEMan: msg->what == %" B_PRIx32 " (%.4s)\n", + message->what, (char*)&(message->what)); BLooper::MessageReceived(message); break; } diff --git a/src/servers/registrar/MessagingService.cpp b/src/servers/registrar/MessagingService.cpp index 5d1758f729..bd8ba8544f 100644 --- a/src/servers/registrar/MessagingService.cpp +++ b/src/servers/registrar/MessagingService.cpp @@ -408,12 +408,13 @@ MessagingService::_CommandProcessor() const messaging_command *command = area->PopCommand(); if (!command) { // something's seriously wrong - ERROR("MessagingService::_CommandProcessor(): area %p (%ld) " - "has command count %ld, but doesn't return any more " - "commands.", area, area->ID(), area->CountCommands()); + ERROR("MessagingService::_CommandProcessor(): area %p (%" + B_PRId32 ") has command count %" B_PRId32 ", but doesn't " + "return any more commands.", area, area->ID(), + area->CountCommands()); break; } -PRINT("MessagingService::_CommandProcessor(): got command %lu\n", +PRINT("MessagingService::_CommandProcessor(): got command %" B_PRIu32 "\n", command->command); // dispatch the command @@ -424,7 +425,7 @@ command->command); command->size - sizeof(messaging_command)); } else { WARNING("MessagingService::_CommandProcessor(): No handler " - "found for command %lu\n", command->command); + "found for command %" B_PRIu32 "\n", command->command); } } @@ -440,7 +441,7 @@ command->command); } else { // Bad, but what can we do? ERROR("MessagingService::_CommandProcessor(): Failed to clone " - "kernel area %ld: %s\n", area->NextKernelAreaID(), + "kernel area %" B_PRId32 ": %s\n", area->NextKernelAreaID(), strerror(error)); } diff --git a/src/servers/registrar/RecentEntries.cpp b/src/servers/registrar/RecentEntries.cpp index 2281864274..ed3d5828a0 100644 --- a/src/servers/registrar/RecentEntries.cpp +++ b/src/servers/registrar/RecentEntries.cpp @@ -245,10 +245,10 @@ RecentEntries::Print() std::list::iterator item; int counter = 1; for (item = fEntryList.begin(); item != fEntryList.end(); item++) { - printf("%d: device == '%ld', dir == '%lld', name == '%s', app == '%s', " - "index == %ld\n", counter++, (*item)->ref.device, - (*item)->ref.directory, (*item)->ref.name, (*item)->sig.c_str(), - (*item)->index); + printf("%d: device == '%" B_PRIdDEV "', dir == '%" B_PRIdINO "', " + "name == '%s', app == '%s', index == %" B_PRId32 "\n", counter++, + (*item)->ref.device, (*item)->ref.directory, (*item)->ref.name, + (*item)->sig.c_str(), (*item)->index); } return B_OK; } @@ -308,9 +308,10 @@ RecentEntries::Save(FILE* file, const char *description, const char *tag) for (std::list::iterator item = list.begin(); item != list.end(); i++, item++) { recent_entry *entry = *item; - if (entry) - fprintf(file, " \"%s\" %ld", entry->sig.c_str(), entry->index); - else { + if (entry) { + fprintf(file, " \"%s\" %" B_PRId32, entry->sig.c_str(), + entry->index); + } else { D(PRINT("WARNING: RecentEntries::Save(): The entry %ld " "entries from the front of the compiled recent_entry* " "list for the entry ref (%ld, %lld, '%s') was found to " diff --git a/src/servers/registrar/mime/AssociatedTypes.cpp b/src/servers/registrar/mime/AssociatedTypes.cpp index 7e507cda36..8865da9e81 100644 --- a/src/servers/registrar/mime/AssociatedTypes.cpp +++ b/src/servers/registrar/mime/AssociatedTypes.cpp @@ -398,9 +398,10 @@ AssociatedTypes::BuildAssociatedTypesTable() if (!err) { fHaveDoneFullBuild = true; // PrintToStream(); + } else { + DBG(OUT("Mime::AssociatedTypes::BuildAssociatedTypesTable() failed, " + "error code == 0x%" B_PRIx32 "\n", err)); } - else - DBG(OUT("Mime::AssociatedTypes::BuildAssociatedTypesTable() failed, error code == 0x%lx\n", err)); return err; } diff --git a/src/servers/registrar/mime/InstalledTypes.cpp b/src/servers/registrar/mime/InstalledTypes.cpp index 8823786d08..12b0c20ba0 100644 --- a/src/servers/registrar/mime/InstalledTypes.cpp +++ b/src/servers/registrar/mime/InstalledTypes.cpp @@ -406,7 +406,8 @@ InstalledTypes::_BuildInstalledTypesList() // Add this supertype std::map::iterator i; if (_AddSupertype(supertype, i) != B_OK) - DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding supertype '%s': 0x%lx\n", + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList()" + " -- Error adding supertype '%s': 0x%" B_PRIx32 "\n", supertype, err)); Supertype &supertypeRef = fSupertypes[supertype]; @@ -435,7 +436,8 @@ InstalledTypes::_BuildInstalledTypesList() // Add the subtype if (_AddSubtype(supertypeRef, type.String() + subStart + 1) != B_OK) { - DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList() -- Error adding subtype '%s/%s': 0x%lx\n", + DBG(OUT("Mime::InstalledTypes::BuildInstalledTypesList()" + " -- Error adding subtype '%s/%s': 0x%" B_PRIx32 "\n", supertype, type.String() + subStart + 1, err)); } } diff --git a/src/servers/registrar/mime/MimeUpdateThread.cpp b/src/servers/registrar/mime/MimeUpdateThread.cpp index d68ea3cb94..5b530fbc1b 100644 --- a/src/servers/registrar/mime/MimeUpdateThread.cpp +++ b/src/servers/registrar/mime/MimeUpdateThread.cpp @@ -125,9 +125,9 @@ MimeUpdateThread::ThreadFunction() status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, 500000); if (error) OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination notification " - "failed with error 0x%lx\n", error); + "failed with error 0x%" B_PRIx32 "\n", error); } - DBG(OUT("(id: %ld) exiting mime update thread with result 0x%lx\n", + DBG(OUT("(id: %ld) exiting mime update thread with result 0x%" B_PRIx32 "\n", find_thread(NULL), err)); return err; } diff --git a/src/servers/registrar/mime/RegistrarThreadManager.cpp b/src/servers/registrar/mime/RegistrarThreadManager.cpp index a8cff5a201..7c924d9058 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.cpp +++ b/src/servers/registrar/mime/RegistrarThreadManager.cpp @@ -199,8 +199,9 @@ RegistrarThreadManager::KillThreads() (*i)->Id())); status_t err = kill_thread((*i)->Id()); if (err) - OUT("WARNING: RegistrarThreadManager::KillThreads(): kill_thread(%ld) failed with " - "error code 0x%lx\n", (*i)->Id(), err); + OUT("WARNING: RegistrarThreadManager::KillThreads(): kill_thread(%" + B_PRId32 ") failed with error code 0x%" B_PRIx32 "\n", + (*i)->Id(), err); } DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread %ld\n", (*i)->Id())); diff --git a/src/servers/registrar/mime/SnifferRules.cpp b/src/servers/registrar/mime/SnifferRules.cpp index 287461fd6b..e61885f31d 100644 --- a/src/servers/registrar/mime/SnifferRules.cpp +++ b/src/servers/registrar/mime/SnifferRules.cpp @@ -408,8 +408,10 @@ SnifferRules::BuildRuleList() fMaxBytesNeeded = maxBytesNeeded; fHaveDoneFullBuild = true; // PrintToStream(); - } else - DBG(OUT("Mime::SnifferRules::BuildRuleList() failed, error code == 0x%lx\n", err)); + } else { + DBG(OUT("Mime::SnifferRules::BuildRuleList() failed, error code == 0x%" + B_PRIx32 "\n", err)); + } return err; } From a9ee7a51329c8a6c6e205e91907c2a753bb62495 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 3 Aug 2012 15:42:30 +0100 Subject: [PATCH 157/273] Added new BIOS module for calling BIOS interrupts. This module provides an interface for drivers to use to perform calls to the BIOS (only really for use by graphics drivers which need to use the VESA BIOS). It uses the x86emu library from X.org which emulates a real mode x86 CPU. This is necessary for x86_64 as virtual 8086 mode no longer exists there. --- build/jam/Haiku64Image | 2 +- build/jam/HaikuImage | 4 +- headers/os/drivers/bios.h | 73 + src/add-ons/kernel/generic/Jamfile | 1 + src/add-ons/kernel/generic/bios/Jamfile | 17 + src/add-ons/kernel/generic/bios/bios.cpp | 368 + .../kernel/generic/bios/x86emu/debug.c | 496 + .../kernel/generic/bios/x86emu/decode.c | 1092 ++ src/add-ons/kernel/generic/bios/x86emu/fpu.c | 976 ++ src/add-ons/kernel/generic/bios/x86emu/ops.c | 12307 ++++++++++++++++ src/add-ons/kernel/generic/bios/x86emu/ops2.c | 3008 ++++ .../kernel/generic/bios/x86emu/prim_ops.c | 2859 ++++ src/add-ons/kernel/generic/bios/x86emu/sys.c | 550 + .../kernel/generic/bios/x86emu/validate.c | 769 + .../kernel/generic/bios/x86emu/x86emu.h | 197 + .../kernel/generic/bios/x86emu/x86emu/debug.h | 209 + .../generic/bios/x86emu/x86emu/decode.h | 87 + .../kernel/generic/bios/x86emu/x86emu/fpu.h | 60 + .../generic/bios/x86emu/x86emu/fpu_regs.h | 119 + .../kernel/generic/bios/x86emu/x86emu/ops.h | 45 + .../generic/bios/x86emu/x86emu/prim_asm.h | 1053 ++ .../generic/bios/x86emu/x86emu/prim_ops.h | 141 + .../generic/bios/x86emu/x86emu/prim_x86_gcc.h | 77 + .../kernel/generic/bios/x86emu/x86emu/regs.h | 342 + .../kernel/generic/bios/x86emu/x86emu/types.h | 80 + .../generic/bios/x86emu/x86emu/x86emui.h | 100 + 26 files changed, 25029 insertions(+), 3 deletions(-) create mode 100644 headers/os/drivers/bios.h create mode 100644 src/add-ons/kernel/generic/bios/Jamfile create mode 100644 src/add-ons/kernel/generic/bios/bios.cpp create mode 100644 src/add-ons/kernel/generic/bios/x86emu/debug.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/decode.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/fpu.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/ops.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/ops2.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/prim_ops.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/sys.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/validate.c create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h create mode 100644 src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index ba5c32f4bc..c841c2322d 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -65,7 +65,7 @@ AddFilesToHaikuImage system add-ons kernel debugger AddFilesToHaikuImage system add-ons kernel file_systems : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; AddFilesToHaikuImage system add-ons kernel generic - : $(ATA_ONLY)ata_adapter dpc locked_pool scsi_periph tty ; + : $(ATA_ONLY)ata_adapter bios dpc locked_pool scsi_periph tty ; AddFilesToHaikuImage system add-ons kernel partitioning_systems : intel session ; diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 61adf50d76..29b914cafe 100644 --- a/build/jam/HaikuImage +++ b/build/jam/HaikuImage @@ -244,8 +244,8 @@ AddFilesToHaikuImage system add-ons kernel debugger AddFilesToHaikuImage system add-ons kernel file_systems : $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ; AddFilesToHaikuImage system add-ons kernel generic - : $(ATA_ONLY)ata_adapter dpc $(IDE_ONLY)ide_adapter locked_pool mpu401 - scsi_periph tty ; + : $(ATA_ONLY)ata_adapter $(X86_ONLY)bios dpc $(IDE_ONLY)ide_adapter + locked_pool mpu401 scsi_periph tty ; AddFilesToHaikuImage system add-ons kernel partitioning_systems : amiga_rdb apple efi_gpt intel session ; AddFilesToHaikuImage system add-ons kernel interrupt_controllers diff --git a/headers/os/drivers/bios.h b/headers/os/drivers/bios.h new file mode 100644 index 0000000000..c756649eb1 --- /dev/null +++ b/headers/os/drivers/bios.h @@ -0,0 +1,73 @@ +/* + * Copyright 2012, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _BIOS_MODULE_H_ +#define _BIOS_MODULE_H_ + + +#include +#include + + +/*! BIOS call interface. + + This module provides a mechanism to call PC BIOS interrupts (e.g. to use + the VESA BIOS). + + Basic usage is as follows: + - Call bios_module_info::prepare(). This sets up memory mappings and + obtains exclusive access to the BIOS (only 1 thread is able to use the + BIOS at a time). + - Allocate memory for data that will be passed to BIOS interrupts using + bios_module_info::allocate_mem(). This returns a virtual address, to + get the physical address to pass to the BIOS use + bios_module_info::physical_address(). + - Call the BIOS with bios_module_info::interrupt(). + - Get the virtual location of any physical addresses returned using + bios_module_info::virtual_address(). + - Release the BIOS and free created memory mappings with + bios_module_info::finish(). + +*/ + + +// Cookie for the BIOS module functions. +typedef struct BIOSState bios_state; + + +// Registers to pass to a BIOS interrupt. +struct bios_regs { + uint32 eax; + uint32 ebx; + uint32 ecx; + uint32 edx; + uint32 edi; + uint32 esi; + uint32 ebp; + uint32 eflags; + uint32 ds; + uint32 es; + uint32 fs; + uint32 gs; +}; + + +struct bios_module_info { + module_info info; + + status_t (*prepare)(bios_state** _state); + status_t (*interrupt)(bios_state* state, uint8 vector, bios_regs* regs); + void (*finish)(bios_state* state); + + // Memory management methods. + void* (*allocate_mem)(bios_state* state, size_t size); + uint32 (*physical_address)(bios_state* state, void* virtualAddress); + void* (*virtual_address)(bios_state* state, uint32 physicalAddress); +}; + + +#define B_BIOS_MODULE_NAME "generic/bios/v1" + + +#endif // _BIOS_MODULE_H_ diff --git a/src/add-ons/kernel/generic/Jamfile b/src/add-ons/kernel/generic/Jamfile index a2a6bfc1fa..1ac20bafc0 100644 --- a/src/add-ons/kernel/generic/Jamfile +++ b/src/add-ons/kernel/generic/Jamfile @@ -2,6 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel generic ; SubInclude HAIKU_TOP src add-ons kernel generic ata_adapter ; SubInclude HAIKU_TOP src add-ons kernel generic atomizer ; +SubInclude HAIKU_TOP src add-ons kernel generic bios ; SubInclude HAIKU_TOP src add-ons kernel generic dpc ; SubInclude HAIKU_TOP src add-ons kernel generic ide_adapter ; SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ; diff --git a/src/add-ons/kernel/generic/bios/Jamfile b/src/add-ons/kernel/generic/bios/Jamfile new file mode 100644 index 0000000000..faa5ec4370 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/Jamfile @@ -0,0 +1,17 @@ +SubDir HAIKU_TOP src add-ons kernel generic bios ; + +UsePrivateKernelHeaders ; + +SEARCH_SOURCE += [ FDirName $(SUBDIR) x86emu ] ; + +KernelAddon bios : + decode.c + fpu.c + ops.c + ops2.c + prim_ops.c + sys.c + + bios.cpp +; + diff --git a/src/add-ons/kernel/generic/bios/bios.cpp b/src/add-ons/kernel/generic/bios/bios.cpp new file mode 100644 index 0000000000..8ae2745852 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/bios.cpp @@ -0,0 +1,368 @@ +/* + * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include + +#include + +#include +#include +#include + +#include "x86emu.h" + + +struct BIOSState { + BIOSState() + : + mapped_address(0), + bios_area(-1), + ram_area(-1), + allocated_size(0) + { + } + + ~BIOSState() + { + if (bios_area >= 0) + delete_area(bios_area); + if (ram_area >= 0) + delete_area(ram_area); + } + + addr_t mapped_address; + area_id bios_area; + area_id ram_area; + size_t allocated_size; +}; + + +// BIOS memory layout definitions. +static const uint32 kBDABase = 0; +static const uint32 kBDASize = 0x1000; +static const uint32 kEBDABase = 0x90000; +static const uint32 kEBDASize = 0x70000; +static const uint32 kRAMBase = 0x1000; +static const uint32 kRAMSize = 0x8f000; +static const uint32 kStackSize = 0x1000; +static const uint32 kTotalSize = 0x100000; + + +static sem_id sBIOSLock; +static BIOSState* sCurrentBIOSState; + + +// #pragma mark - X86EMU hooks. + + +static x86emuu8 +x86emu_pio_inb(X86EMU_pioAddr port) +{ + return in8(port); +} + + +static x86emuu16 +x86emu_pio_inw(X86EMU_pioAddr port) +{ + return in16(port); +} + + +static x86emuu32 +x86emu_pio_inl(X86EMU_pioAddr port) +{ + return in32(port); +} + + +static void +x86emu_pio_outb(X86EMU_pioAddr port, x86emuu8 data) +{ + out8(data, port); +} + + +static void +x86emu_pio_outw(X86EMU_pioAddr port, x86emuu16 data) +{ + out16(data, port); +} + + +static void +x86emu_pio_outl(X86EMU_pioAddr port, x86emuu32 data) +{ + out32(data, port); +} + + +static X86EMU_pioFuncs x86emu_pio_funcs = { + x86emu_pio_inb, + x86emu_pio_inw, + x86emu_pio_inl, + x86emu_pio_outb, + x86emu_pio_outw, + x86emu_pio_outl, +}; + + +static x86emuu8 +x86emu_mem_rdb(x86emuu32 addr) +{ + return *(x86emuu8*)((addr_t)addr + sCurrentBIOSState->mapped_address); +} + + +static x86emuu16 +x86emu_mem_rdw(x86emuu32 addr) +{ + return *(x86emuu16*)((addr_t)addr + sCurrentBIOSState->mapped_address); +} + + +static x86emuu32 +x86emu_mem_rdl(x86emuu32 addr) +{ + return *(x86emuu32*)((addr_t)addr + sCurrentBIOSState->mapped_address); +} + + +static void +x86emu_mem_wrb(x86emuu32 addr, x86emuu8 val) +{ + *(x86emuu8*)((addr_t)addr + sCurrentBIOSState->mapped_address) = val; +} + + +static void +x86emu_mem_wrw(x86emuu32 addr, x86emuu16 val) +{ + *(x86emuu16*)((addr_t)addr + sCurrentBIOSState->mapped_address) = val; +} + + +static void +x86emu_mem_wrl(x86emuu32 addr, x86emuu32 val) +{ + *(x86emuu32*)((addr_t)addr + sCurrentBIOSState->mapped_address) = val; +} + + +static X86EMU_memFuncs x86emu_mem_funcs = { + x86emu_mem_rdb, + x86emu_mem_rdw, + x86emu_mem_rdl, + x86emu_mem_wrb, + x86emu_mem_wrw, + x86emu_mem_wrl, +}; + + +// #pragma mark - + + +static void* +bios_allocate_mem(bios_state* state, size_t size) +{ + // Simple allocator for memory to pass to the BIOS. No need for a complex + // allocator here, there is only a few allocations per BIOS usage. + + size = ROUNDUP(size, 4); + + if (state->allocated_size + size > kRAMSize) + return NULL; + + void* address + = (void*)(state->mapped_address + kRAMBase + state->allocated_size); + state->allocated_size += size; + + return address; +} + + +static uint32 +bios_physical_address(bios_state* state, void* virtualAddress) +{ + return (uint32)((addr_t)virtualAddress - state->mapped_address); +} + + +static void* +bios_virtual_address(bios_state* state, uint32 physicalAddress) +{ + return (void*)((addr_t)physicalAddress + state->mapped_address); +} + + +static status_t +bios_prepare(bios_state** _state) +{ + status_t status; + + BIOSState* state = new(std::nothrow) BIOSState; + if (state == NULL) + return B_NO_MEMORY; + ObjectDeleter stateDeleter(state); + + // Reserve a chunk of address space to map at. + status = vm_reserve_address_range(VMAddressSpace::KernelID(), + (void**)&state->mapped_address, B_ANY_KERNEL_ADDRESS, + kTotalSize, 0); + if (status != B_OK) + return status; + + // Map RAM for for the BIOS. + state->ram_area = create_area("bios ram", (void**)&state->mapped_address, + B_EXACT_ADDRESS, kBDASize + kRAMSize, B_NO_LOCK, B_KERNEL_READ_AREA + | B_KERNEL_WRITE_AREA); + if (state->ram_area < B_OK) { + vm_unreserve_address_range(VMAddressSpace::KernelID(), + (void*)state->mapped_address, kTotalSize); + return state->ram_area; + } + + // Copy the interrupt vectors and the BIOS data area. + status = vm_memcpy_from_physical((void*)state->mapped_address, kBDABase, + kBDASize, false); + if (status != B_OK) { + vm_unreserve_address_range(VMAddressSpace::KernelID(), + (void*)state->mapped_address, kTotalSize); + return status; + } + *((uint32 *)state->mapped_address) = 0xdeadbeef; + + // Map the extended BIOS data area and VGA memory. + void* address = (void*)(state->mapped_address + kEBDABase); + state->bios_area = map_physical_memory("bios", kEBDABase, kEBDASize, + B_EXACT_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &address); + if (state->bios_area < B_OK) { + vm_unreserve_address_range(VMAddressSpace::KernelID(), + (void*)state->mapped_address, kTotalSize); + return state->bios_area; + } + + // Attempt to acquire exclusive access to the BIOS. + acquire_sem(sBIOSLock); + + stateDeleter.Detach(); + *_state = state; + return B_OK; +} + + +static status_t +bios_interrupt(bios_state* state, uint8 vector, bios_regs* regs) +{ + sCurrentBIOSState = state; + + // Allocate a stack. + void* stack = bios_allocate_mem(state, kStackSize); + if (stack == NULL) + return B_NO_MEMORY; + uint32 stackTop = bios_physical_address(state, stack) + kStackSize; + + // X86EMU finishes when it encounters a HLT instruction, allocate a + // byte to store one in and set the return address of the interrupt to + // point to it. + void* halt = bios_allocate_mem(state, 1); + if (halt == NULL) + return B_NO_MEMORY; + *(uint8*)halt = 0xF4; + + // Copy in the registers. + memset(&M, 0, sizeof(M)); + M.x86.R_EAX = regs->eax; + M.x86.R_EBX = regs->ebx; + M.x86.R_ECX = regs->ecx; + M.x86.R_EDX = regs->edx; + M.x86.R_EDI = regs->edi; + M.x86.R_ESI = regs->esi; + M.x86.R_EBP = regs->ebp; + M.x86.R_EFLG = regs->eflags | X86_EFLAGS_INTERRUPT | X86_EFLAGS_RESERVED1; + M.x86.R_EIP = bios_physical_address(state, halt); + M.x86.R_CS = 0x0; + M.x86.R_DS = regs->ds; + M.x86.R_ES = regs->es; + M.x86.R_FS = regs->fs; + M.x86.R_GS = regs->gs; + M.x86.R_SS = stackTop >> 4; + M.x86.R_ESP = stackTop - (M.x86.R_SS << 4); + + /* Run the interrupt. */ + X86EMU_setupPioFuncs(&x86emu_pio_funcs); + X86EMU_setupMemFuncs(&x86emu_mem_funcs); + X86EMU_prepareForInt(vector); + X86EMU_exec(); + + // Copy back modified data. + regs->eax = M.x86.R_EAX; + regs->ebx = M.x86.R_EBX; + regs->ecx = M.x86.R_ECX; + regs->edx = M.x86.R_EDX; + regs->edi = M.x86.R_EDI; + regs->esi = M.x86.R_ESI; + regs->ebp = M.x86.R_EBP; + regs->eflags = M.x86.R_EFLG; + regs->ds = M.x86.R_DS; + regs->es = M.x86.R_ES; + regs->fs = M.x86.R_FS; + regs->gs = M.x86.R_GS; + + return B_OK; +} + + +static void +bios_finish(bios_state* state) +{ + release_sem(sBIOSLock); + + delete state; +} + + +static status_t +std_ops(int32 op, ...) +{ + switch (op) { + case B_MODULE_INIT: + sBIOSLock = create_sem(1, "bios lock"); + if (sBIOSLock < B_OK) + return sBIOSLock; + + return B_OK; + case B_MODULE_UNINIT: + delete_sem(sBIOSLock); + return B_OK; + default: + return B_ERROR; + } +} + + +static bios_module_info sBIOSModule = { + { + B_BIOS_MODULE_NAME, + 0, + std_ops + }, + + bios_prepare, + bios_interrupt, + bios_finish, + bios_allocate_mem, + bios_physical_address, + bios_virtual_address +}; + + +module_info *modules[] = { + (module_info*)&sBIOSModule, + NULL +}; diff --git a/src/add-ons/kernel/generic/bios/x86emu/debug.c b/src/add-ons/kernel/generic/bios/x86emu/debug.c new file mode 100644 index 0000000000..cee36f595d --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/debug.c @@ -0,0 +1,496 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file contains the code to handle debugging of the +* emulator. +* +****************************************************************************/ + +#include "x86emu/x86emui.h" +#include +#include +#ifndef NO_SYS_HEADERS +#include +#include +#endif + +/*----------------------------- Implementation ----------------------------*/ + +#ifdef DEBUG + +static void print_encoded_bytes(u16 s, u16 o); +static void print_decoded_instruction(void); +static int parse_line(char *s, int *ps, int *n); + +/* should look something like debug's output. */ +void +X86EMU_trace_regs(void) +{ + if (DEBUG_TRACE()) { + x86emu_dump_regs(); + } + if (DEBUG_DECODE() && !DEBUG_DECODE_NOPRINT()) { + printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip); + print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip); + print_decoded_instruction(); + } +} + +void +X86EMU_trace_xregs(void) +{ + if (DEBUG_TRACE()) { + x86emu_dump_xregs(); + } +} + +void +x86emu_just_disassemble(void) +{ + /* + * This routine called if the flag DEBUG_DISASSEMBLE is set kind + * of a hack! + */ + printk("%04x:%04x ", M.x86.saved_cs, M.x86.saved_ip); + print_encoded_bytes(M.x86.saved_cs, M.x86.saved_ip); + print_decoded_instruction(); +} + +static void +disassemble_forward(u16 seg, u16 off, int n) +{ + X86EMU_sysEnv tregs; + int i; + u8 op1; + + /* + * hack, hack, hack. What we do is use the exact machinery set up + * for execution, except that now there is an additional state + * flag associated with the "execution", and we are using a copy + * of the register struct. All the major opcodes, once fully + * decoded, have the following two steps: TRACE_REGS(r,m); + * SINGLE_STEP(r,m); which disappear if DEBUG is not defined to + * the preprocessor. The TRACE_REGS macro expands to: + * + * if (debug&DEBUG_DISASSEMBLE) + * {just_disassemble(); goto EndOfInstruction;} + * if (debug&DEBUG_TRACE) trace_regs(r,m); + * + * ...... and at the last line of the routine. + * + * EndOfInstruction: end_instr(); + * + * Up to the point where TRACE_REG is expanded, NO modifications + * are done to any register EXCEPT the IP register, for fetch and + * decoding purposes. + * + * This was done for an entirely different reason, but makes a + * nice way to get the system to help debug codes. + */ + tregs = M; + tregs.x86.R_IP = off; + tregs.x86.R_CS = seg; + + /* reset the decoding buffers */ + tregs.x86.enc_str_pos = 0; + tregs.x86.enc_pos = 0; + + /* turn on the "disassemble only, no execute" flag */ + tregs.x86.debug |= DEBUG_DISASSEMBLE_F; + + /* DUMP NEXT n instructions to screen in straight_line fashion */ + /* + * This looks like the regular instruction fetch stream, except + * that when this occurs, each fetched opcode, upon seeing the + * DEBUG_DISASSEMBLE flag set, exits immediately after decoding + * the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!! + * Note the use of a copy of the register structure... + */ + for (i = 0; i < n; i++) { + op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); + (x86emu_optab[op1]) (op1); + } + /* end major hack mode. */ +} + +void +x86emu_check_ip_access(void) +{ + /* NULL as of now */ +} + +void +x86emu_check_sp_access(void) +{ +} + +void +x86emu_check_mem_access(u32 dummy) +{ + /* check bounds, etc */ +} + +void +x86emu_check_data_access(uint dummy1, uint dummy2) +{ + /* check bounds, etc */ +} + +void +x86emu_inc_decoded_inst_len(int x) +{ + M.x86.enc_pos += x; +} + +void +x86emu_decode_printf(const char *x) +{ + sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", x); + M.x86.enc_str_pos += strlen(x); +} + +void +x86emu_decode_printf2(const char *x, int y) +{ + char temp[100]; + + snprintf(temp, sizeof(temp), x, y); + sprintf(M.x86.decoded_buf + M.x86.enc_str_pos, "%s", temp); + M.x86.enc_str_pos += strlen(temp); +} + +void +x86emu_end_instr(void) +{ + M.x86.enc_str_pos = 0; + M.x86.enc_pos = 0; +} + +static void +print_encoded_bytes(u16 s, u16 o) +{ + int i; + char buf1[64]; + + for (i = 0; i < M.x86.enc_pos; i++) { + sprintf(buf1 + 2 * i, "%02x", fetch_data_byte_abs(s, o + i)); + } + printk("%-20s", buf1); +} + +static void +print_decoded_instruction(void) +{ + printk("%s", M.x86.decoded_buf); +} + +void +x86emu_print_int_vect(u16 iv) +{ + u16 seg, off; + + if (iv > 256) + return; + seg = fetch_data_word_abs(0, iv * 4); + off = fetch_data_word_abs(0, iv * 4 + 2); + printk("%04x:%04x ", seg, off); +} + +void +X86EMU_dump_memory(u16 seg, u16 off, u32 amt) +{ + u32 start = off & 0xfffffff0; + u32 end = (off + 16) & 0xfffffff0; + u32 i; + u32 current; + + current = start; + while (end <= off + amt) { + printk("%04x:%04x ", seg, start); + for (i = start; i < off; i++) + printk(" "); + for (; i < end; i++) + printk("%02x ", fetch_data_byte_abs(seg, i)); + printk("\n"); + start = end; + end = start + 16; + } +} + +void +x86emu_single_step(void) +{ + return; + char s[1024]; + int ps[10]; + int ntok; + int cmd; + int done; + int segment; + int offset; + static int breakpoint; + static int noDecode = 1; + + //char *p; + + if (DEBUG_BREAK()) { + if (M.x86.saved_ip != breakpoint) { + return; + } + else { + M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; + M.x86.debug |= DEBUG_TRACE_F; + M.x86.debug &= ~DEBUG_BREAK_F; + print_decoded_instruction(); + X86EMU_trace_regs(); + } + } + done = 0; + offset = M.x86.saved_ip; + while (!done) { + printk("-"); + //p = fgets(s, 1023, stdin); + cmd = parse_line(s, ps, &ntok); + switch (cmd) { + case 'u': + disassemble_forward(M.x86.saved_cs, (u16) offset, 10); + break; + case 'd': + if (ntok == 2) { + segment = M.x86.saved_cs; + offset = ps[1]; + X86EMU_dump_memory(segment, (u16) offset, 16); + offset += 16; + } + else if (ntok == 3) { + segment = ps[1]; + offset = ps[2]; + X86EMU_dump_memory(segment, (u16) offset, 16); + offset += 16; + } + else { + segment = M.x86.saved_cs; + X86EMU_dump_memory(segment, (u16) offset, 16); + offset += 16; + } + break; + case 'c': + M.x86.debug ^= DEBUG_TRACECALL_F; + break; + case 's': + M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F; + break; + case 'r': + X86EMU_trace_regs(); + break; + case 'x': + X86EMU_trace_xregs(); + break; + case 'g': + if (ntok == 2) { + breakpoint = ps[1]; + if (noDecode) { + M.x86.debug |= DEBUG_DECODE_NOPRINT_F; + } + else { + M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; + } + M.x86.debug &= ~DEBUG_TRACE_F; + M.x86.debug |= DEBUG_BREAK_F; + done = 1; + } + break; + case 'q': + M.x86.debug |= DEBUG_EXIT; + return; + case 'P': + noDecode = (noDecode) ? 0 : 1; + printk("Toggled decoding to %s\n", (noDecode) ? "FALSE" : "TRUE"); + break; + case 't': + case 0: + done = 1; + break; + } + } +} + +int +X86EMU_trace_on(void) +{ + return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F; +} + +int +X86EMU_trace_off(void) +{ + return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F); +} + +static int +parse_line(char *s, int *ps, int *n) +{ + int cmd; + + *n = 0; + while (*s == ' ' || *s == '\t') + s++; + ps[*n] = *s; + switch (*s) { + case '\n': + *n += 1; + return 0; + default: + cmd = *s; + *n += 1; + } + + while (1) { + while (*s != ' ' && *s != '\t' && *s != '\n') + s++; + + if (*s == '\n') + return cmd; + + while (*s == ' ' || *s == '\t') + s++; + + //sscanf(s, "%x", &ps[*n]); + *n += 1; + } +} + +#endif /* DEBUG */ + +void +x86emu_dump_regs(void) +{ + printk("\tAX=%04x ", M.x86.R_AX); + printk("BX=%04x ", M.x86.R_BX); + printk("CX=%04x ", M.x86.R_CX); + printk("DX=%04x ", M.x86.R_DX); + printk("SP=%04x ", M.x86.R_SP); + printk("BP=%04x ", M.x86.R_BP); + printk("SI=%04x ", M.x86.R_SI); + printk("DI=%04x\n", M.x86.R_DI); + printk("\tDS=%04x ", M.x86.R_DS); + printk("ES=%04x ", M.x86.R_ES); + printk("SS=%04x ", M.x86.R_SS); + printk("CS=%04x ", M.x86.R_CS); + printk("IP=%04x ", M.x86.R_IP); + if (ACCESS_FLAG(F_OF)) + printk("OV "); /* CHECKED... */ + else + printk("NV "); + if (ACCESS_FLAG(F_DF)) + printk("DN "); + else + printk("UP "); + if (ACCESS_FLAG(F_IF)) + printk("EI "); + else + printk("DI "); + if (ACCESS_FLAG(F_SF)) + printk("NG "); + else + printk("PL "); + if (ACCESS_FLAG(F_ZF)) + printk("ZR "); + else + printk("NZ "); + if (ACCESS_FLAG(F_AF)) + printk("AC "); + else + printk("NA "); + if (ACCESS_FLAG(F_PF)) + printk("PE "); + else + printk("PO "); + if (ACCESS_FLAG(F_CF)) + printk("CY "); + else + printk("NC "); + printk("\n"); +} + +void +x86emu_dump_xregs(void) +{ + printk("\tEAX=%08x ", M.x86.R_EAX); + printk("EBX=%08x ", M.x86.R_EBX); + printk("ECX=%08x ", M.x86.R_ECX); + printk("EDX=%08x \n", M.x86.R_EDX); + printk("\tESP=%08x ", M.x86.R_ESP); + printk("EBP=%08x ", M.x86.R_EBP); + printk("ESI=%08x ", M.x86.R_ESI); + printk("EDI=%08x\n", M.x86.R_EDI); + printk("\tDS=%04x ", M.x86.R_DS); + printk("ES=%04x ", M.x86.R_ES); + printk("SS=%04x ", M.x86.R_SS); + printk("CS=%04x ", M.x86.R_CS); + printk("EIP=%08x\n\t", M.x86.R_EIP); + if (ACCESS_FLAG(F_OF)) + printk("OV "); /* CHECKED... */ + else + printk("NV "); + if (ACCESS_FLAG(F_DF)) + printk("DN "); + else + printk("UP "); + if (ACCESS_FLAG(F_IF)) + printk("EI "); + else + printk("DI "); + if (ACCESS_FLAG(F_SF)) + printk("NG "); + else + printk("PL "); + if (ACCESS_FLAG(F_ZF)) + printk("ZR "); + else + printk("NZ "); + if (ACCESS_FLAG(F_AF)) + printk("AC "); + else + printk("NA "); + if (ACCESS_FLAG(F_PF)) + printk("PE "); + else + printk("PO "); + if (ACCESS_FLAG(F_CF)) + printk("CY "); + else + printk("NC "); + printk("\n"); +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/decode.c b/src/add-ons/kernel/generic/bios/x86emu/decode.c new file mode 100644 index 0000000000..12f8fb84b3 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/decode.c @@ -0,0 +1,1092 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file includes subroutines which are related to +* instruction decoding and accessess of immediate data via IP. etc. +* +****************************************************************************/ + +#include +#include "x86emu/x86emui.h" + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +REMARKS: +Handles any pending asychronous interrupts. +****************************************************************************/ +static void +x86emu_intr_handle(void) +{ + u8 intno; + + if (M.x86.intr & INTR_SYNCH) { + intno = M.x86.intno; + if (_X86EMU_intrTab[intno]) { + (*_X86EMU_intrTab[intno]) (intno); + } + else { + push_word((u16) M.x86.R_FLG); + CLEAR_FLAG(F_IF); + CLEAR_FLAG(F_TF); + push_word(M.x86.R_CS); + M.x86.R_CS = mem_access_word(intno * 4 + 2); + push_word(M.x86.R_IP); + M.x86.R_IP = mem_access_word(intno * 4); + M.x86.intr = 0; + } + } +} + +/**************************************************************************** +PARAMETERS: +intrnum - Interrupt number to raise + +REMARKS: +Raise the specified interrupt to be handled before the execution of the +next instruction. +****************************************************************************/ +void +x86emu_intr_raise(u8 intrnum) +{ + M.x86.intno = intrnum; + M.x86.intr |= INTR_SYNCH; +} + +/**************************************************************************** +REMARKS: +Main execution loop for the emulator. We return from here when the system +halts, which is normally caused by a stack fault when we return from the +original real mode call. +****************************************************************************/ +void +X86EMU_exec(void) +{ + u8 op1; + + M.x86.intr = 0; + DB(x86emu_end_instr(); + ) + + for (;;) { + DB(if (CHECK_IP_FETCH()) + x86emu_check_ip_access();) + /* If debugging, save the IP and CS values. */ + SAVE_IP_CS(M.x86.R_CS, M.x86.R_IP); + INC_DECODED_INST_LEN(1); + if (M.x86.intr) { + if (M.x86.intr & INTR_HALTED) { + DB(if (M.x86.R_SP != 0) { + printk("halted\n"); X86EMU_trace_regs();} + else { + if (M.x86.debug) + printk("Service completed successfully\n");} + ) + return; + } + if (((M.x86.intr & INTR_SYNCH) && + (M.x86.intno == 0 || M.x86.intno == 2)) || + !ACCESS_FLAG(F_IF)) { + x86emu_intr_handle(); + } + } + op1 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); + (*x86emu_optab[op1]) (op1); + if (M.x86.debug & DEBUG_EXIT) { + M.x86.debug &= ~DEBUG_EXIT; + return; + } + } +} + +/**************************************************************************** +REMARKS: +Halts the system by setting the halted system flag. +****************************************************************************/ +void +X86EMU_halt_sys(void) +{ + M.x86.intr |= INTR_HALTED; +} + +/**************************************************************************** +PARAMETERS: +mod - Mod value from decoded byte +regh - Reg h value from decoded byte +regl - Reg l value from decoded byte + +REMARKS: +Raise the specified interrupt to be handled before the execution of the +next instruction. + +NOTE: Do not inline this function, as (*sys_rdb) is already inline! +****************************************************************************/ +void +fetch_decode_modrm(int *mod, int *regh, int *regl) +{ + int fetched; + + DB(if (CHECK_IP_FETCH()) + x86emu_check_ip_access();) + fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); + INC_DECODED_INST_LEN(1); + *mod = (fetched >> 6) & 0x03; + *regh = (fetched >> 3) & 0x07; + *regl = (fetched >> 0) & 0x07; +} + +/**************************************************************************** +RETURNS: +Immediate byte value read from instruction queue + +REMARKS: +This function returns the immediate byte from the instruction queue, and +moves the instruction pointer to the next value. + +NOTE: Do not inline this function, as (*sys_rdb) is already inline! +****************************************************************************/ +u8 +fetch_byte_imm(void) +{ + u8 fetched; + + DB(if (CHECK_IP_FETCH()) + x86emu_check_ip_access();) + fetched = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); + INC_DECODED_INST_LEN(1); + return fetched; +} + +/**************************************************************************** +RETURNS: +Immediate word value read from instruction queue + +REMARKS: +This function returns the immediate byte from the instruction queue, and +moves the instruction pointer to the next value. + +NOTE: Do not inline this function, as (*sys_rdw) is already inline! +****************************************************************************/ +u16 +fetch_word_imm(void) +{ + u16 fetched; + + DB(if (CHECK_IP_FETCH()) + x86emu_check_ip_access();) + fetched = (*sys_rdw) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP)); + M.x86.R_IP += 2; + INC_DECODED_INST_LEN(2); + return fetched; +} + +/**************************************************************************** +RETURNS: +Immediate lone value read from instruction queue + +REMARKS: +This function returns the immediate byte from the instruction queue, and +moves the instruction pointer to the next value. + +NOTE: Do not inline this function, as (*sys_rdw) is already inline! +****************************************************************************/ +u32 +fetch_long_imm(void) +{ + u32 fetched; + + DB(if (CHECK_IP_FETCH()) + x86emu_check_ip_access();) + fetched = (*sys_rdl) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP)); + M.x86.R_IP += 4; + INC_DECODED_INST_LEN(4); + return fetched; +} + +/**************************************************************************** +RETURNS: +Value of the default data segment + +REMARKS: +Inline function that returns the default data segment for the current +instruction. + +On the x86 processor, the default segment is not always DS if there is +no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to +addresses relative to SS (ie: on the stack). So, at the minimum, all +decodings of addressing modes would have to set/clear a bit describing +whether the access is relative to DS or SS. That is the function of the +cpu-state-varible M.x86.mode. There are several potential states: + + repe prefix seen (handled elsewhere) + repne prefix seen (ditto) + + cs segment override + ds segment override + es segment override + fs segment override + gs segment override + ss segment override + + ds/ss select (in absense of override) + +Each of the above 7 items are handled with a bit in the mode field. +****************************************************************************/ +_INLINE u32 +get_data_segment(void) +{ +#define GET_SEGMENT(segment) + switch (M.x86.mode & SYSMODE_SEGMASK) { + case 0: /* default case: use ds register */ + case SYSMODE_SEGOVR_DS: + case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS: + return M.x86.R_DS; + case SYSMODE_SEG_DS_SS: /* non-overridden, use ss register */ + return M.x86.R_SS; + case SYSMODE_SEGOVR_CS: + case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS: + return M.x86.R_CS; + case SYSMODE_SEGOVR_ES: + case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS: + return M.x86.R_ES; + case SYSMODE_SEGOVR_FS: + case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS: + return M.x86.R_FS; + case SYSMODE_SEGOVR_GS: + case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS: + return M.x86.R_GS; + case SYSMODE_SEGOVR_SS: + case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS: + return M.x86.R_SS; + default: +#ifdef DEBUG + printk("error: should not happen: multiple overrides.\n"); +#endif + HALT_SYS(); + return 0; + } +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to load data from + +RETURNS: +Byte value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u8 +fetch_data_byte(uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + return (*sys_rdb) ((get_data_segment() << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to load data from + +RETURNS: +Word value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u16 +fetch_data_word(uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + return (*sys_rdw) ((get_data_segment() << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to load data from + +RETURNS: +Long value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u32 +fetch_data_long(uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + return (*sys_rdl) ((get_data_segment() << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to load data from +offset - Offset to load data from + +RETURNS: +Byte value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u8 +fetch_data_byte_abs(uint segment, uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + return (*sys_rdb) (((u32) segment << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to load data from +offset - Offset to load data from + +RETURNS: +Word value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u16 +fetch_data_word_abs(uint segment, uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + return (*sys_rdw) (((u32) segment << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to load data from +offset - Offset to load data from + +RETURNS: +Long value read from the absolute memory location. + +NOTE: Do not inline this function as (*sys_rdX) is already inline! +****************************************************************************/ +u32 +fetch_data_long_abs(uint segment, uint offset) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + return (*sys_rdl) (((u32) segment << 4) + offset); +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a word value to an segmented memory location. The segment used is +the current 'default' segment, which may have been overridden. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_byte(uint offset, u8 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + (*sys_wrb) ((get_data_segment() << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a word value to an segmented memory location. The segment used is +the current 'default' segment, which may have been overridden. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_word(uint offset, u16 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + (*sys_wrw) ((get_data_segment() << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a long value to an segmented memory location. The segment used is +the current 'default' segment, which may have been overridden. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_long(uint offset, u32 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access((u16) get_data_segment(), offset); +#endif + (*sys_wrl) ((get_data_segment() << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to store data at +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a byte value to an absolute memory location. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_byte_abs(uint segment, uint offset, u8 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + (*sys_wrb) (((u32) segment << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to store data at +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a word value to an absolute memory location. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_word_abs(uint segment, uint offset, u16 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + (*sys_wrw) (((u32) segment << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +segment - Segment to store data at +offset - Offset to store data at +val - Value to store + +REMARKS: +Writes a long value to an absolute memory location. + +NOTE: Do not inline this function as (*sys_wrX) is already inline! +****************************************************************************/ +void +store_data_long_abs(uint segment, uint offset, u32 val) +{ +#ifdef DEBUG + if (CHECK_DATA_ACCESS()) + x86emu_check_data_access(segment, offset); +#endif + (*sys_wrl) (((u32) segment << 4) + offset, val); +} + +/**************************************************************************** +PARAMETERS: +reg - Register to decode + +RETURNS: +Pointer to the appropriate register + +REMARKS: +Return a pointer to the register given by the R/RM field of the +modrm byte, for byte operands. Also enables the decoding of instructions. +****************************************************************************/ +u8 * +decode_rm_byte_register(int reg) +{ + switch (reg) { + case 0: + DECODE_PRINTF("AL"); + return &M.x86.R_AL; + case 1: + DECODE_PRINTF("CL"); + return &M.x86.R_CL; + case 2: + DECODE_PRINTF("DL"); + return &M.x86.R_DL; + case 3: + DECODE_PRINTF("BL"); + return &M.x86.R_BL; + case 4: + DECODE_PRINTF("AH"); + return &M.x86.R_AH; + case 5: + DECODE_PRINTF("CH"); + return &M.x86.R_CH; + case 6: + DECODE_PRINTF("DH"); + return &M.x86.R_DH; + case 7: + DECODE_PRINTF("BH"); + return &M.x86.R_BH; + } + HALT_SYS(); + return NULL; /* NOT REACHED OR REACHED ON ERROR */ +} + +/**************************************************************************** +PARAMETERS: +reg - Register to decode + +RETURNS: +Pointer to the appropriate register + +REMARKS: +Return a pointer to the register given by the R/RM field of the +modrm byte, for word operands. Also enables the decoding of instructions. +****************************************************************************/ +u16 * +decode_rm_word_register(int reg) +{ + switch (reg) { + case 0: + DECODE_PRINTF("AX"); + return &M.x86.R_AX; + case 1: + DECODE_PRINTF("CX"); + return &M.x86.R_CX; + case 2: + DECODE_PRINTF("DX"); + return &M.x86.R_DX; + case 3: + DECODE_PRINTF("BX"); + return &M.x86.R_BX; + case 4: + DECODE_PRINTF("SP"); + return &M.x86.R_SP; + case 5: + DECODE_PRINTF("BP"); + return &M.x86.R_BP; + case 6: + DECODE_PRINTF("SI"); + return &M.x86.R_SI; + case 7: + DECODE_PRINTF("DI"); + return &M.x86.R_DI; + } + HALT_SYS(); + return NULL; /* NOTREACHED OR REACHED ON ERROR */ +} + +/**************************************************************************** +PARAMETERS: +reg - Register to decode + +RETURNS: +Pointer to the appropriate register + +REMARKS: +Return a pointer to the register given by the R/RM field of the +modrm byte, for dword operands. Also enables the decoding of instructions. +****************************************************************************/ +u32 * +decode_rm_long_register(int reg) +{ + switch (reg) { + case 0: + DECODE_PRINTF("EAX"); + return &M.x86.R_EAX; + case 1: + DECODE_PRINTF("ECX"); + return &M.x86.R_ECX; + case 2: + DECODE_PRINTF("EDX"); + return &M.x86.R_EDX; + case 3: + DECODE_PRINTF("EBX"); + return &M.x86.R_EBX; + case 4: + DECODE_PRINTF("ESP"); + return &M.x86.R_ESP; + case 5: + DECODE_PRINTF("EBP"); + return &M.x86.R_EBP; + case 6: + DECODE_PRINTF("ESI"); + return &M.x86.R_ESI; + case 7: + DECODE_PRINTF("EDI"); + return &M.x86.R_EDI; + } + HALT_SYS(); + return NULL; /* NOTREACHED OR REACHED ON ERROR */ +} + +/**************************************************************************** +PARAMETERS: +reg - Register to decode + +RETURNS: +Pointer to the appropriate register + +REMARKS: +Return a pointer to the register given by the R/RM field of the +modrm byte, for word operands, modified from above for the weirdo +special case of segreg operands. Also enables the decoding of instructions. +****************************************************************************/ +u16 * +decode_rm_seg_register(int reg) +{ + switch (reg) { + case 0: + DECODE_PRINTF("ES"); + return &M.x86.R_ES; + case 1: + DECODE_PRINTF("CS"); + return &M.x86.R_CS; + case 2: + DECODE_PRINTF("SS"); + return &M.x86.R_SS; + case 3: + DECODE_PRINTF("DS"); + return &M.x86.R_DS; + case 4: + DECODE_PRINTF("FS"); + return &M.x86.R_FS; + case 5: + DECODE_PRINTF("GS"); + return &M.x86.R_GS; + case 6: + case 7: + DECODE_PRINTF("ILLEGAL SEGREG"); + break; + } + HALT_SYS(); + return NULL; /* NOT REACHED OR REACHED ON ERROR */ +} + +/* + * + * return offset from the SIB Byte + */ +u32 +decode_sib_address(int sib, int mod) +{ + u32 base = 0, i = 0, scale = 1; + + switch (sib & 0x07) { + case 0: + DECODE_PRINTF("[EAX]"); + base = M.x86.R_EAX; + break; + case 1: + DECODE_PRINTF("[ECX]"); + base = M.x86.R_ECX; + break; + case 2: + DECODE_PRINTF("[EDX]"); + base = M.x86.R_EDX; + break; + case 3: + DECODE_PRINTF("[EBX]"); + base = M.x86.R_EBX; + break; + case 4: + DECODE_PRINTF("[ESP]"); + base = M.x86.R_ESP; + M.x86.mode |= SYSMODE_SEG_DS_SS; + break; + case 5: + if (mod == 0) { + base = fetch_long_imm(); + DECODE_PRINTF2("%08x", base); + } + else { + DECODE_PRINTF("[EBP]"); + base = M.x86.R_ESP; + M.x86.mode |= SYSMODE_SEG_DS_SS; + } + break; + case 6: + DECODE_PRINTF("[ESI]"); + base = M.x86.R_ESI; + break; + case 7: + DECODE_PRINTF("[EDI]"); + base = M.x86.R_EDI; + break; + } + switch ((sib >> 3) & 0x07) { + case 0: + DECODE_PRINTF("[EAX"); + i = M.x86.R_EAX; + break; + case 1: + DECODE_PRINTF("[ECX"); + i = M.x86.R_ECX; + break; + case 2: + DECODE_PRINTF("[EDX"); + i = M.x86.R_EDX; + break; + case 3: + DECODE_PRINTF("[EBX"); + i = M.x86.R_EBX; + break; + case 4: + i = 0; + break; + case 5: + DECODE_PRINTF("[EBP"); + i = M.x86.R_EBP; + break; + case 6: + DECODE_PRINTF("[ESI"); + i = M.x86.R_ESI; + break; + case 7: + DECODE_PRINTF("[EDI"); + i = M.x86.R_EDI; + break; + } + scale = 1 << ((sib >> 6) & 0x03); + if (((sib >> 3) & 0x07) != 4) { + if (scale == 1) { + DECODE_PRINTF("]"); + } + else { + DECODE_PRINTF2("*%d]", scale); + } + } + return base + (i * scale); +} + +/**************************************************************************** +PARAMETERS: +rm - RM value to decode + +RETURNS: +Offset in memory for the address decoding + +REMARKS: +Return the offset given by mod=00 addressing. Also enables the +decoding of instructions. + +NOTE: The code which specifies the corresponding segment (ds vs ss) + below in the case of [BP+..]. The assumption here is that at the + point that this subroutine is called, the bit corresponding to + SYSMODE_SEG_DS_SS will be zero. After every instruction + except the segment override instructions, this bit (as well + as any bits indicating segment overrides) will be clear. So + if a SS access is needed, set this bit. Otherwise, DS access + occurs (unless any of the segment override bits are set). +****************************************************************************/ +u32 +decode_rm00_address(int rm) +{ + u32 offset; + int sib; + + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + /* 32-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF("[EAX]"); + return M.x86.R_EAX; + case 1: + DECODE_PRINTF("[ECX]"); + return M.x86.R_ECX; + case 2: + DECODE_PRINTF("[EDX]"); + return M.x86.R_EDX; + case 3: + DECODE_PRINTF("[EBX]"); + return M.x86.R_EBX; + case 4: + sib = fetch_byte_imm(); + return decode_sib_address(sib, 0); + case 5: + offset = fetch_long_imm(); + DECODE_PRINTF2("[%08x]", offset); + return offset; + case 6: + DECODE_PRINTF("[ESI]"); + return M.x86.R_ESI; + case 7: + DECODE_PRINTF("[EDI]"); + return M.x86.R_EDI; + } + HALT_SYS(); + } + else { + /* 16-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF("[BX+SI]"); + return (M.x86.R_BX + M.x86.R_SI) & 0xffff; + case 1: + DECODE_PRINTF("[BX+DI]"); + return (M.x86.R_BX + M.x86.R_DI) & 0xffff; + case 2: + DECODE_PRINTF("[BP+SI]"); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_SI) & 0xffff; + case 3: + DECODE_PRINTF("[BP+DI]"); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_DI) & 0xffff; + case 4: + DECODE_PRINTF("[SI]"); + return M.x86.R_SI; + case 5: + DECODE_PRINTF("[DI]"); + return M.x86.R_DI; + case 6: + offset = fetch_word_imm(); + DECODE_PRINTF2("[%04x]", offset); + return offset; + case 7: + DECODE_PRINTF("[BX]"); + return M.x86.R_BX; + } + HALT_SYS(); + } + return 0; +} + +/**************************************************************************** +PARAMETERS: +rm - RM value to decode + +RETURNS: +Offset in memory for the address decoding + +REMARKS: +Return the offset given by mod=01 addressing. Also enables the +decoding of instructions. +****************************************************************************/ +u32 +decode_rm01_address(int rm) +{ + int displacement = 0; + int sib; + + /* Fetch disp8 if no SIB byte */ + if (!((M.x86.mode & SYSMODE_PREFIX_ADDR) && (rm == 4))) + displacement = (s8) fetch_byte_imm(); + + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + /* 32-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF2("%d[EAX]", displacement); + return M.x86.R_EAX + displacement; + case 1: + DECODE_PRINTF2("%d[ECX]", displacement); + return M.x86.R_ECX + displacement; + case 2: + DECODE_PRINTF2("%d[EDX]", displacement); + return M.x86.R_EDX + displacement; + case 3: + DECODE_PRINTF2("%d[EBX]", displacement); + return M.x86.R_EBX + displacement; + case 4: + sib = fetch_byte_imm(); + displacement = (s8) fetch_byte_imm(); + DECODE_PRINTF2("%d", displacement); + return decode_sib_address(sib, 1) + displacement; + case 5: + DECODE_PRINTF2("%d[EBP]", displacement); + return M.x86.R_EBP + displacement; + case 6: + DECODE_PRINTF2("%d[ESI]", displacement); + return M.x86.R_ESI + displacement; + case 7: + DECODE_PRINTF2("%d[EDI]", displacement); + return M.x86.R_EDI + displacement; + } + HALT_SYS(); + } + else { + /* 16-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF2("%d[BX+SI]", displacement); + return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; + case 1: + DECODE_PRINTF2("%d[BX+DI]", displacement); + return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; + case 2: + DECODE_PRINTF2("%d[BP+SI]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; + case 3: + DECODE_PRINTF2("%d[BP+DI]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; + case 4: + DECODE_PRINTF2("%d[SI]", displacement); + return (M.x86.R_SI + displacement) & 0xffff; + case 5: + DECODE_PRINTF2("%d[DI]", displacement); + return (M.x86.R_DI + displacement) & 0xffff; + case 6: + DECODE_PRINTF2("%d[BP]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + displacement) & 0xffff; + case 7: + DECODE_PRINTF2("%d[BX]", displacement); + return (M.x86.R_BX + displacement) & 0xffff; + } + HALT_SYS(); + } + return 0; /* SHOULD NOT HAPPEN */ +} + +/**************************************************************************** +PARAMETERS: +rm - RM value to decode + +RETURNS: +Offset in memory for the address decoding + +REMARKS: +Return the offset given by mod=10 addressing. Also enables the +decoding of instructions. +****************************************************************************/ +u32 +decode_rm10_address(int rm) +{ + u32 displacement = 0; + int sib; + + /* Fetch disp16 if 16-bit addr mode */ + if (!(M.x86.mode & SYSMODE_PREFIX_ADDR)) + displacement = (u16) fetch_word_imm(); + else { + /* Fetch disp32 if no SIB byte */ + if (rm != 4) + displacement = (u32) fetch_long_imm(); + } + + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + /* 32-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF2("%08x[EAX]", displacement); + return M.x86.R_EAX + displacement; + case 1: + DECODE_PRINTF2("%08x[ECX]", displacement); + return M.x86.R_ECX + displacement; + case 2: + DECODE_PRINTF2("%08x[EDX]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return M.x86.R_EDX + displacement; + case 3: + DECODE_PRINTF2("%08x[EBX]", displacement); + return M.x86.R_EBX + displacement; + case 4: + sib = fetch_byte_imm(); + displacement = (u32) fetch_long_imm(); + DECODE_PRINTF2("%08x", displacement); + return decode_sib_address(sib, 2) + displacement; + break; + case 5: + DECODE_PRINTF2("%08x[EBP]", displacement); + return M.x86.R_EBP + displacement; + case 6: + DECODE_PRINTF2("%08x[ESI]", displacement); + return M.x86.R_ESI + displacement; + case 7: + DECODE_PRINTF2("%08x[EDI]", displacement); + return M.x86.R_EDI + displacement; + } + HALT_SYS(); + } + else { + /* 16-bit addressing */ + switch (rm) { + case 0: + DECODE_PRINTF2("%04x[BX+SI]", displacement); + return (M.x86.R_BX + M.x86.R_SI + displacement) & 0xffff; + case 1: + DECODE_PRINTF2("%04x[BX+DI]", displacement); + return (M.x86.R_BX + M.x86.R_DI + displacement) & 0xffff; + case 2: + DECODE_PRINTF2("%04x[BP+SI]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_SI + displacement) & 0xffff; + case 3: + DECODE_PRINTF2("%04x[BP+DI]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + M.x86.R_DI + displacement) & 0xffff; + case 4: + DECODE_PRINTF2("%04x[SI]", displacement); + return (M.x86.R_SI + displacement) & 0xffff; + case 5: + DECODE_PRINTF2("%04x[DI]", displacement); + return (M.x86.R_DI + displacement) & 0xffff; + case 6: + DECODE_PRINTF2("%04x[BP]", displacement); + M.x86.mode |= SYSMODE_SEG_DS_SS; + return (M.x86.R_BP + displacement) & 0xffff; + case 7: + DECODE_PRINTF2("%04x[BX]", displacement); + return (M.x86.R_BX + displacement) & 0xffff; + } + HALT_SYS(); + } + return 0; + /*NOTREACHED */ +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/fpu.c b/src/add-ons/kernel/generic/bios/x86emu/fpu.c new file mode 100644 index 0000000000..0dab05ce38 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/fpu.c @@ -0,0 +1,976 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file contains the code to implement the decoding and +* emulation of the FPU instructions. +* +****************************************************************************/ + +#include "x86emu/x86emui.h" + +/*----------------------------- Implementation ----------------------------*/ + +/* opcode=0xd8 */ +void +x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("ESC D8\n"); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_d9_tab[] = { + "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", + "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", + + "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", + "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", + + "FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ", + "FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t", +}; + +static const char *x86emu_fpu_op_d9_tab1[] = { + "FLD\t", "FLD\t", "FLD\t", "FLD\t", + "FLD\t", "FLD\t", "FLD\t", "FLD\t", + + "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", + "FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t", + + "FNOP", "ESC_D9", "ESC_D9", "ESC_D9", + "ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9", + + "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", + "FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t", + + "FCHS", "FABS", "ESC_D9", "ESC_D9", + "FTST", "FXAM", "ESC_D9", "ESC_D9", + + "FLD1", "FLDL2T", "FLDL2E", "FLDPI", + "FLDLG2", "FLDLN2", "FLDZ", "ESC_D9", + + "F2XM1", "FYL2X", "FPTAN", "FPATAN", + "FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP", + + "FPREM", "FYL2XP1", "FSQRT", "ESC_D9", + "FRNDINT", "FSCALE", "ESC_D9", "ESC_D9", +}; + +#endif /* DEBUG */ + +/* opcode=0xd9 */ +void +x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (mod != 3) { + DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl); + } + else { + DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]); + } +#endif + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + if (rh < 4) { + DECODE_PRINTF2("ST(%d)\n", stkelem); + } + else { + DECODE_PRINTF("\n"); + } + break; + } +#ifdef X86EMU_FPU_PRESENT + /* execute */ + switch (mod) { + case 3: + switch (rh) { + case 0: + x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem); + break; + case 1: + x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem); + break; + case 2: + switch (rl) { + case 0: + x86emu_fpu_R_nop(); + break; + default: + x86emu_fpu_illegal(); + break; + } + case 3: + x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem); + break; + case 4: + switch (rl) { + case 0: + x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP); + break; + case 4: + x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP); + break; + default: + /* 2,3,6,7 */ + x86emu_fpu_illegal(); + break; + } + break; + + case 5: + switch (rl) { + case 0: + x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP); + break; + case 2: + x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP); + break; + case 3: + x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP); + break; + case 4: + x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP); + break; + case 6: + x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP); + break; + default: + /* 7 */ + x86emu_fpu_illegal(); + break; + } + break; + + case 6: + switch (rl) { + case 0: + x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP); + break; + case 2: + x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP); + break; + case 3: + x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP); + break; + case 4: + x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_illegal(); + break; + case 6: + x86emu_fpu_R_decstp(); + break; + case 7: + x86emu_fpu_R_incstp(); + break; + } + break; + + case 7: + switch (rl) { + case 0: + x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP); + break; + case 2: + x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP); + break; + case 3: + x86emu_fpu_illegal(); + break; + case 4: + x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP); + break; + case 6: + case 7: + default: + x86emu_fpu_illegal(); + break; + } + break; + + default: + switch (rh) { + case 0: + x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset); + break; + case 1: + x86emu_fpu_illegal(); + break; + case 2: + x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset); + break; + case 3: + x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset); + break; + case 4: + x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset); + break; + case 5: + x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset); + break; + case 6: + x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset); + break; + case 7: + x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset); + break; + } + } + } +#else + (void) destoffset; + (void) stkelem; +#endif /* X86EMU_FPU_PRESENT */ + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_da_tab[] = { + "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", + "FICOMP\tDWORD PTR ", + "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", + "FIDIVR\tDWORD PTR ", + + "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", + "FICOMP\tDWORD PTR ", + "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", + "FIDIVR\tDWORD PTR ", + + "FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ", + "FICOMP\tDWORD PTR ", + "FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ", + "FIDIVR\tDWORD PTR ", + + "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", + "ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ", +}; + +#endif /* DEBUG */ + +/* opcode=0xda */ +void +x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + DECODE_PRINTF2("\tST(%d),ST\n", stkelem); + break; + } +#ifdef X86EMU_FPU_PRESENT + switch (mod) { + case 3: + x86emu_fpu_illegal(); + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset); + break; + case 1: + x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset); + break; + case 2: + x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset); + break; + case 3: + x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset); + break; + case 4: + x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset); + break; + case 5: + x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset); + break; + case 6: + x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset); + break; + case 7: + x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset); + break; + } + } +#else + (void) destoffset; + (void) stkelem; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_db_tab[] = { + "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", + "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", + + "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", + "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", + + "FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ", + "ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ", +}; + +#endif /* DEBUG */ + +/* opcode=0xdb */ +void +x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (mod != 3) { + DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl); + } + else if (rh == 4) { /* === 11 10 0 nnn */ + switch (rl) { + case 0: + DECODE_PRINTF("FENI\n"); + break; + case 1: + DECODE_PRINTF("FDISI\n"); + break; + case 2: + DECODE_PRINTF("FCLEX\n"); + break; + case 3: + DECODE_PRINTF("FINIT\n"); + break; + } + } + else { + DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl)); + } +#endif /* DEBUG */ + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + break; + case 1: + destoffset = decode_rm01_address(rl); + break; + case 2: + destoffset = decode_rm10_address(rl); + break; + case 3: /* register to register */ + break; + } +#ifdef X86EMU_FPU_PRESENT + /* execute */ + switch (mod) { + case 3: + switch (rh) { + case 4: + switch (rl) { + case 0: + x86emu_fpu_R_feni(); + break; + case 1: + x86emu_fpu_R_fdisi(); + break; + case 2: + x86emu_fpu_R_fclex(); + break; + case 3: + x86emu_fpu_R_finit(); + break; + default: + x86emu_fpu_illegal(); + break; + } + break; + default: + x86emu_fpu_illegal(); + break; + } + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset); + break; + case 1: + x86emu_fpu_illegal(); + break; + case 2: + x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset); + break; + case 3: + x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset); + break; + case 4: + x86emu_fpu_illegal(); + break; + case 5: + x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset); + break; + case 6: + x86emu_fpu_illegal(); + break; + case 7: + x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset); + break; + } + } +#else + (void) destoffset; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG +static const char *x86emu_fpu_op_dc_tab[] = { + "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", + "FCOMP\tQWORD PTR ", + "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", + "FDIVR\tQWORD PTR ", + + "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", + "FCOMP\tQWORD PTR ", + "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", + "FDIVR\tQWORD PTR ", + + "FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ", + "FCOMP\tQWORD PTR ", + "FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ", + "FDIVR\tQWORD PTR ", + + "FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t", + "FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t", +}; +#endif /* DEBUG */ + +/* opcode=0xdc */ +void +x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + DECODE_PRINTF2("\tST(%d),ST\n", stkelem); + break; + } +#ifdef X86EMU_FPU_PRESENT + /* execute */ + switch (mod) { + case 3: + switch (rh) { + case 0: + x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP); + break; + case 2: + x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP); + break; + case 3: + x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP); + break; + case 4: + x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP); + break; + case 6: + x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP); + break; + case 7: + x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP); + break; + } + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset); + break; + case 1: + x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset); + break; + case 2: + x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset); + break; + case 3: + x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset); + break; + case 4: + x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset); + break; + case 5: + x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset); + break; + case 6: + x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset); + break; + case 7: + x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset); + break; + } + } +#else + (void) destoffset; + (void) stkelem; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_dd_tab[] = { + "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", + "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", + + "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", + "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", + + "FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ", + "FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t", + + "FFREE\t", "FXCH\t", "FST\t", "FSTP\t", + "ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,", +}; + +#endif /* DEBUG */ + +/* opcode=0xdd */ +void +x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + DECODE_PRINTF2("\tST(%d),ST\n", stkelem); + break; + } +#ifdef X86EMU_FPU_PRESENT + switch (mod) { + case 3: + switch (rh) { + case 0: + x86emu_fpu_R_ffree(stkelem); + break; + case 1: + x86emu_fpu_R_fxch(stkelem); + break; + case 2: + x86emu_fpu_R_fst(stkelem); /* register version */ + break; + case 3: + x86emu_fpu_R_fstp(stkelem); /* register version */ + break; + default: + x86emu_fpu_illegal(); + break; + } + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset); + break; + case 1: + x86emu_fpu_illegal(); + break; + case 2: + x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset); + break; + case 3: + x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset); + break; + case 4: + x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset); + break; + case 5: + x86emu_fpu_illegal(); + break; + case 6: + x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset); + break; + case 7: + x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset); + break; + } + } +#else + (void) destoffset; + (void) stkelem; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_de_tab[] = { + "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", + "FICOMP\tWORD PTR ", + "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", + "FIDIVR\tWORD PTR ", + + "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", + "FICOMP\tWORD PTR ", + "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", + "FIDIVR\tWORD PTR ", + + "FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ", + "FICOMP\tWORD PTR ", + "FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ", + "FIDIVR\tWORD PTR ", + + "FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t", + "FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t", +}; + +#endif /* DEBUG */ + +/* opcode=0xde */ +void +x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + DECODE_PRINTF2("\tST(%d),ST\n", stkelem); + break; + } +#ifdef X86EMU_FPU_PRESENT + switch (mod) { + case 3: + switch (rh) { + case 0: + x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP); + break; + case 1: + x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP); + break; + case 2: + x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP); + break; + case 3: + if (stkelem == 1) + x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP); + else + x86emu_fpu_illegal(); + break; + case 4: + x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP); + break; + case 5: + x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP); + break; + case 6: + x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP); + break; + case 7: + x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP); + break; + } + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset); + break; + case 1: + x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset); + break; + case 2: + x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset); + break; + case 3: + x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset); + break; + case 4: + x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset); + break; + case 5: + x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset); + break; + case 6: + x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset); + break; + case 7: + x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset); + break; + } + } +#else + (void) destoffset; + (void) stkelem; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} + +#ifdef DEBUG + +static const char *x86emu_fpu_op_df_tab[] = { + /* mod == 00 */ + "FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", + "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", + "FISTP\tQWORD PTR ", + + /* mod == 01 */ + "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", + "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", + "FISTP\tQWORD PTR ", + + /* mod == 10 */ + "FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ", + "FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ", + "FISTP\tQWORD PTR ", + + /* mod == 11 */ + "FFREE\t", "FXCH\t", "FST\t", "FSTP\t", + "ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F," +}; + +#endif /* DEBUG */ + +/* opcode=0xdf */ +void +x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset = 0; + u8 stkelem = 0; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + break; + case 3: /* register to register */ + stkelem = (u8) rl; + DECODE_PRINTF2("\tST(%d)\n", stkelem); + break; + } +#ifdef X86EMU_FPU_PRESENT + switch (mod) { + case 3: + switch (rh) { + case 0: + x86emu_fpu_R_ffree(stkelem); + break; + case 1: + x86emu_fpu_R_fxch(stkelem); + break; + case 2: + x86emu_fpu_R_fst(stkelem); /* register version */ + break; + case 3: + x86emu_fpu_R_fstp(stkelem); /* register version */ + break; + default: + x86emu_fpu_illegal(); + break; + } + break; + default: + switch (rh) { + case 0: + x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset); + break; + case 1: + x86emu_fpu_illegal(); + break; + case 2: + x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset); + break; + case 3: + x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset); + break; + case 4: + x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset); + break; + case 5: + x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset); + break; + case 6: + x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset); + break; + case 7: + x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset); + break; + } + } +#else + (void) destoffset; + (void) stkelem; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR_NO_TRACE(); +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/ops.c b/src/add-ons/kernel/generic/bios/x86emu/ops.c new file mode 100644 index 0000000000..76b83581f5 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/ops.c @@ -0,0 +1,12307 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file includes subroutines to implement the decoding +* and emulation of all the x86 processor instructions. +* +* There are approximately 250 subroutines in here, which correspond +* to the 256 byte-"opcodes" found on the 8086. The table which +* dispatches this is found in the files optab.[ch]. +* +* Each opcode proc has a comment preceeding it which gives it's table +* address. Several opcodes are missing (undefined) in the table. +* +* Each proc includes information for decoding (DECODE_PRINTF and +* DECODE_PRINTF2), debugging (TRACE_REGS, SINGLE_STEP), and misc +* functions (START_OF_INSTR, END_OF_INSTR). +* +* Many of the procedures are *VERY* similar in coding. This has +* allowed for a very large amount of code to be generated in a fairly +* short amount of time (i.e. cut, paste, and modify). The result is +* that much of the code below could have been folded into subroutines +* for a large reduction in size of this file. The downside would be +* that there would be a penalty in execution speed. The file could +* also have been *MUCH* larger by inlining certain functions which +* were called. This could have resulted even faster execution. The +* prime directive I used to decide whether to inline the code or to +* modularize it, was basically: 1) no unnecessary subroutine calls, +* 2) no routines more than about 200 lines in size, and 3) modularize +* any code that I might not get right the first time. The fetch_* +* subroutines fall into the latter category. The The decode_* fall +* into the second category. The coding of the "switch(mod){ .... }" +* in many of the subroutines below falls into the first category. +* Especially, the coding of {add,and,or,sub,...}_{byte,word} +* subroutines are an especially glaring case of the third guideline. +* Since so much of the code is cloned from other modules (compare +* opcode #00 to opcode #01), making the basic operations subroutine +* calls is especially important; otherwise mistakes in coding an +* "add" would represent a nightmare in maintenance. +* +****************************************************************************/ + +#include "x86emu/x86emui.h" + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +PARAMETERS: +op1 - Instruction op code + +REMARKS: +Handles illegal opcodes. +****************************************************************************/ +static void +x86emuOp_illegal_op(u8 op1) +{ + START_OF_INSTR(); + if (M.x86.R_SP != 0) { + DECODE_PRINTF("ILLEGAL X86 OPCODE\n"); + TRACE_REGS(); + DB(printk("%04x:%04x: %02X ILLEGAL X86 OPCODE!\n", + M.x86.R_CS, M.x86.R_IP - 1, op1)); + HALT_SYS(); + } + else { + /* If we get here, it means the stack pointer is back to zero + * so we are just returning from an emulator service call + * so therte is no need to display an error message. We trap + * the emulator with an 0xF1 opcode to finish the service + * call. + */ + X86EMU_halt_sys(); + } + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x00 +****************************************************************************/ +static void +x86emuOp_add_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + u8 *destreg, *srcreg; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("ADD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x01 +****************************************************************************/ +static void +x86emuOp_add_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("ADD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = add_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x02 +****************************************************************************/ +static void +x86emuOp_add_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("ADD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x03 +****************************************************************************/ +static void +x86emuOp_add_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("ADD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = add_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x04 +****************************************************************************/ +static void +x86emuOp_add_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("ADD\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = add_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x05 +****************************************************************************/ +static void +x86emuOp_add_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("ADD\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("ADD\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = add_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = add_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x06 +****************************************************************************/ +static void +x86emuOp_push_ES(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tES\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_ES); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x07 +****************************************************************************/ +static void +x86emuOp_pop_ES(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("POP\tES\n"); + TRACE_AND_STEP(); + M.x86.R_ES = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x08 +****************************************************************************/ +static void +x86emuOp_or_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("OR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x09 +****************************************************************************/ +static void +x86emuOp_or_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("OR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = or_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0a +****************************************************************************/ +static void +x86emuOp_or_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("OR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0b +****************************************************************************/ +static void +x86emuOp_or_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("OR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = or_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0c +****************************************************************************/ +static void +x86emuOp_or_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("OR\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = or_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0d +****************************************************************************/ +static void +x86emuOp_or_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("OR\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("OR\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = or_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = or_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0e +****************************************************************************/ +static void +x86emuOp_push_CS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tCS\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_CS); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f. Escape for two-byte opcode (286 or better) +****************************************************************************/ +static void +x86emuOp_two_byte(u8 X86EMU_UNUSED(op1)) +{ + u8 op2 = (*sys_rdb) (((u32) M.x86.R_CS << 4) + (M.x86.R_IP++)); + + INC_DECODED_INST_LEN(1); + (*x86emu_optab2[op2]) (op2); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x10 +****************************************************************************/ +static void +x86emuOp_adc_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("ADC\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x11 +****************************************************************************/ +static void +x86emuOp_adc_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("ADC\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = adc_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x12 +****************************************************************************/ +static void +x86emuOp_adc_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("ADC\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x13 +****************************************************************************/ +static void +x86emuOp_adc_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("ADC\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = adc_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x14 +****************************************************************************/ +static void +x86emuOp_adc_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("ADC\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = adc_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x15 +****************************************************************************/ +static void +x86emuOp_adc_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("ADC\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("ADC\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = adc_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = adc_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x16 +****************************************************************************/ +static void +x86emuOp_push_SS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tSS\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_SS); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x17 +****************************************************************************/ +static void +x86emuOp_pop_SS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("POP\tSS\n"); + TRACE_AND_STEP(); + M.x86.R_SS = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x18 +****************************************************************************/ +static void +x86emuOp_sbb_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("SBB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x19 +****************************************************************************/ +static void +x86emuOp_sbb_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SBB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sbb_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1a +****************************************************************************/ +static void +x86emuOp_sbb_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("SBB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1b +****************************************************************************/ +static void +x86emuOp_sbb_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SBB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sbb_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1c +****************************************************************************/ +static void +x86emuOp_sbb_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("SBB\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = sbb_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1d +****************************************************************************/ +static void +x86emuOp_sbb_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("SBB\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("SBB\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = sbb_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = sbb_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1e +****************************************************************************/ +static void +x86emuOp_push_DS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tDS\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_DS); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x1f +****************************************************************************/ +static void +x86emuOp_pop_DS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("POP\tDS\n"); + TRACE_AND_STEP(); + M.x86.R_DS = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x20 +****************************************************************************/ +static void +x86emuOp_and_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("AND\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x21 +****************************************************************************/ +static void +x86emuOp_and_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("AND\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = and_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x22 +****************************************************************************/ +static void +x86emuOp_and_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("AND\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x23 +****************************************************************************/ +static void +x86emuOp_and_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("AND\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_long(*destreg, srcval); + break; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_word(*destreg, srcval); + break; + } + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = and_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x24 +****************************************************************************/ +static void +x86emuOp_and_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("AND\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = and_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x25 +****************************************************************************/ +static void +x86emuOp_and_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("AND\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("AND\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = and_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = and_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x26 +****************************************************************************/ +static void +x86emuOp_segovr_ES(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("ES:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_ES; + /* + * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 + * opcode subroutines we do not want to do this. + */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x27 +****************************************************************************/ +static void +x86emuOp_daa(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("DAA\n"); + TRACE_AND_STEP(); + M.x86.R_AL = daa_byte(M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x28 +****************************************************************************/ +static void +x86emuOp_sub_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("SUB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x29 +****************************************************************************/ +static void +x86emuOp_sub_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SUB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = sub_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2a +****************************************************************************/ +static void +x86emuOp_sub_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("SUB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2b +****************************************************************************/ +static void +x86emuOp_sub_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SUB\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = sub_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2c +****************************************************************************/ +static void +x86emuOp_sub_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("SUB\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = sub_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2d +****************************************************************************/ +static void +x86emuOp_sub_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("SUB\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("SUB\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = sub_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = sub_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2e +****************************************************************************/ +static void +x86emuOp_segovr_CS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("CS:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_CS; + /* note no DECODE_CLEAR_SEGOVR here. */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x2f +****************************************************************************/ +static void +x86emuOp_das(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("DAS\n"); + TRACE_AND_STEP(); + M.x86.R_AL = das_byte(M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x30 +****************************************************************************/ +static void +x86emuOp_xor_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("XOR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_byte(destval, *srcreg); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x31 +****************************************************************************/ +static void +x86emuOp_xor_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("XOR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_long(destval, *srcreg); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = xor_word(destval, *srcreg); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x32 +****************************************************************************/ +static void +x86emuOp_xor_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("XOR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x33 +****************************************************************************/ +static void +x86emuOp_xor_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("XOR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = xor_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x34 +****************************************************************************/ +static void +x86emuOp_xor_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("XOR\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + M.x86.R_AL = xor_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x35 +****************************************************************************/ +static void +x86emuOp_xor_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XOR\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("XOR\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = xor_long(M.x86.R_EAX, srcval); + } + else { + M.x86.R_AX = xor_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x36 +****************************************************************************/ +static void +x86emuOp_segovr_SS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("SS:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_SS; + /* no DECODE_CLEAR_SEGOVR ! */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x37 +****************************************************************************/ +static void +x86emuOp_aaa(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("AAA\n"); + TRACE_AND_STEP(); + M.x86.R_AX = aaa_word(M.x86.R_AX); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x38 +****************************************************************************/ +static void +x86emuOp_cmp_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + u8 *destreg, *srcreg; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("CMP\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(destval, *srcreg); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(destval, *srcreg); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(destval, *srcreg); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x39 +****************************************************************************/ +static void +x86emuOp_cmp_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("CMP\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(destval, *srcreg); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(destval, *srcreg); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(destval, *srcreg); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3a +****************************************************************************/ +static void +x86emuOp_cmp_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("CMP\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(*destreg, srcval); + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(*destreg, srcval); + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(*destreg, srcval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3b +****************************************************************************/ +static void +x86emuOp_cmp_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("CMP\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(*destreg, srcval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(*destreg, srcval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(*destreg, srcval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + cmp_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3c +****************************************************************************/ +static void +x86emuOp_cmp_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("CMP\tAL,"); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + cmp_byte(M.x86.R_AL, srcval); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3d +****************************************************************************/ +static void +x86emuOp_cmp_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("CMP\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("CMP\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + cmp_long(M.x86.R_EAX, srcval); + } + else { + cmp_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3e +****************************************************************************/ +static void +x86emuOp_segovr_DS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("DS:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_DS; + /* NO DECODE_CLEAR_SEGOVR! */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x3f +****************************************************************************/ +static void +x86emuOp_aas(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("AAS\n"); + TRACE_AND_STEP(); + M.x86.R_AX = aas_word(M.x86.R_AX); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x40 +****************************************************************************/ +static void +x86emuOp_inc_AX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tEAX\n"); + } + else { + DECODE_PRINTF("INC\tAX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = inc_long(M.x86.R_EAX); + } + else { + M.x86.R_AX = inc_word(M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x41 +****************************************************************************/ +static void +x86emuOp_inc_CX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tECX\n"); + } + else { + DECODE_PRINTF("INC\tCX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = inc_long(M.x86.R_ECX); + } + else { + M.x86.R_CX = inc_word(M.x86.R_CX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x42 +****************************************************************************/ +static void +x86emuOp_inc_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tEDX\n"); + } + else { + DECODE_PRINTF("INC\tDX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDX = inc_long(M.x86.R_EDX); + } + else { + M.x86.R_DX = inc_word(M.x86.R_DX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x43 +****************************************************************************/ +static void +x86emuOp_inc_BX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tEBX\n"); + } + else { + DECODE_PRINTF("INC\tBX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBX = inc_long(M.x86.R_EBX); + } + else { + M.x86.R_BX = inc_word(M.x86.R_BX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x44 +****************************************************************************/ +static void +x86emuOp_inc_SP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tESP\n"); + } + else { + DECODE_PRINTF("INC\tSP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESP = inc_long(M.x86.R_ESP); + } + else { + M.x86.R_SP = inc_word(M.x86.R_SP); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x45 +****************************************************************************/ +static void +x86emuOp_inc_BP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tEBP\n"); + } + else { + DECODE_PRINTF("INC\tBP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBP = inc_long(M.x86.R_EBP); + } + else { + M.x86.R_BP = inc_word(M.x86.R_BP); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x46 +****************************************************************************/ +static void +x86emuOp_inc_SI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tESI\n"); + } + else { + DECODE_PRINTF("INC\tSI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESI = inc_long(M.x86.R_ESI); + } + else { + M.x86.R_SI = inc_word(M.x86.R_SI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x47 +****************************************************************************/ +static void +x86emuOp_inc_DI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tEDI\n"); + } + else { + DECODE_PRINTF("INC\tDI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDI = inc_long(M.x86.R_EDI); + } + else { + M.x86.R_DI = inc_word(M.x86.R_DI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x48 +****************************************************************************/ +static void +x86emuOp_dec_AX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tEAX\n"); + } + else { + DECODE_PRINTF("DEC\tAX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = dec_long(M.x86.R_EAX); + } + else { + M.x86.R_AX = dec_word(M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x49 +****************************************************************************/ +static void +x86emuOp_dec_CX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tECX\n"); + } + else { + DECODE_PRINTF("DEC\tCX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = dec_long(M.x86.R_ECX); + } + else { + M.x86.R_CX = dec_word(M.x86.R_CX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4a +****************************************************************************/ +static void +x86emuOp_dec_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tEDX\n"); + } + else { + DECODE_PRINTF("DEC\tDX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDX = dec_long(M.x86.R_EDX); + } + else { + M.x86.R_DX = dec_word(M.x86.R_DX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4b +****************************************************************************/ +static void +x86emuOp_dec_BX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tEBX\n"); + } + else { + DECODE_PRINTF("DEC\tBX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBX = dec_long(M.x86.R_EBX); + } + else { + M.x86.R_BX = dec_word(M.x86.R_BX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4c +****************************************************************************/ +static void +x86emuOp_dec_SP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tESP\n"); + } + else { + DECODE_PRINTF("DEC\tSP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESP = dec_long(M.x86.R_ESP); + } + else { + M.x86.R_SP = dec_word(M.x86.R_SP); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4d +****************************************************************************/ +static void +x86emuOp_dec_BP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tEBP\n"); + } + else { + DECODE_PRINTF("DEC\tBP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBP = dec_long(M.x86.R_EBP); + } + else { + M.x86.R_BP = dec_word(M.x86.R_BP); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4e +****************************************************************************/ +static void +x86emuOp_dec_SI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tESI\n"); + } + else { + DECODE_PRINTF("DEC\tSI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESI = dec_long(M.x86.R_ESI); + } + else { + M.x86.R_SI = dec_word(M.x86.R_SI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x4f +****************************************************************************/ +static void +x86emuOp_dec_DI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tEDI\n"); + } + else { + DECODE_PRINTF("DEC\tDI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDI = dec_long(M.x86.R_EDI); + } + else { + M.x86.R_DI = dec_word(M.x86.R_DI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x50 +****************************************************************************/ +static void +x86emuOp_push_AX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tEAX\n"); + } + else { + DECODE_PRINTF("PUSH\tAX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EAX); + } + else { + push_word(M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x51 +****************************************************************************/ +static void +x86emuOp_push_CX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tECX\n"); + } + else { + DECODE_PRINTF("PUSH\tCX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_ECX); + } + else { + push_word(M.x86.R_CX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x52 +****************************************************************************/ +static void +x86emuOp_push_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tEDX\n"); + } + else { + DECODE_PRINTF("PUSH\tDX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EDX); + } + else { + push_word(M.x86.R_DX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x53 +****************************************************************************/ +static void +x86emuOp_push_BX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tEBX\n"); + } + else { + DECODE_PRINTF("PUSH\tBX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EBX); + } + else { + push_word(M.x86.R_BX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x54 +****************************************************************************/ +static void +x86emuOp_push_SP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tESP\n"); + } + else { + DECODE_PRINTF("PUSH\tSP\n"); + } + TRACE_AND_STEP(); + /* Always push (E)SP, since we are emulating an i386 and above + * processor. This is necessary as some BIOS'es use this to check + * what type of processor is in the system. + */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_ESP); + } + else { + push_word((u16) (M.x86.R_SP)); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x55 +****************************************************************************/ +static void +x86emuOp_push_BP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tEBP\n"); + } + else { + DECODE_PRINTF("PUSH\tBP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EBP); + } + else { + push_word(M.x86.R_BP); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x56 +****************************************************************************/ +static void +x86emuOp_push_SI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tESI\n"); + } + else { + DECODE_PRINTF("PUSH\tSI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_ESI); + } + else { + push_word(M.x86.R_SI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x57 +****************************************************************************/ +static void +x86emuOp_push_DI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSH\tEDI\n"); + } + else { + DECODE_PRINTF("PUSH\tDI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EDI); + } + else { + push_word(M.x86.R_DI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x58 +****************************************************************************/ +static void +x86emuOp_pop_AX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tEAX\n"); + } + else { + DECODE_PRINTF("POP\tAX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = pop_long(); + } + else { + M.x86.R_AX = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x59 +****************************************************************************/ +static void +x86emuOp_pop_CX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tECX\n"); + } + else { + DECODE_PRINTF("POP\tCX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = pop_long(); + } + else { + M.x86.R_CX = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5a +****************************************************************************/ +static void +x86emuOp_pop_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tEDX\n"); + } + else { + DECODE_PRINTF("POP\tDX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDX = pop_long(); + } + else { + M.x86.R_DX = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5b +****************************************************************************/ +static void +x86emuOp_pop_BX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tEBX\n"); + } + else { + DECODE_PRINTF("POP\tBX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBX = pop_long(); + } + else { + M.x86.R_BX = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5c +****************************************************************************/ +static void +x86emuOp_pop_SP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tESP\n"); + } + else { + DECODE_PRINTF("POP\tSP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESP = pop_long(); + } + else { + M.x86.R_SP = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5d +****************************************************************************/ +static void +x86emuOp_pop_BP(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tEBP\n"); + } + else { + DECODE_PRINTF("POP\tBP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBP = pop_long(); + } + else { + M.x86.R_BP = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5e +****************************************************************************/ +static void +x86emuOp_pop_SI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tESI\n"); + } + else { + DECODE_PRINTF("POP\tSI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESI = pop_long(); + } + else { + M.x86.R_SI = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x5f +****************************************************************************/ +static void +x86emuOp_pop_DI(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POP\tEDI\n"); + } + else { + DECODE_PRINTF("POP\tDI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDI = pop_long(); + } + else { + M.x86.R_DI = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x60 +****************************************************************************/ +static void +x86emuOp_push_all(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSHAD\n"); + } + else { + DECODE_PRINTF("PUSHA\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 old_sp = M.x86.R_ESP; + + push_long(M.x86.R_EAX); + push_long(M.x86.R_ECX); + push_long(M.x86.R_EDX); + push_long(M.x86.R_EBX); + push_long(old_sp); + push_long(M.x86.R_EBP); + push_long(M.x86.R_ESI); + push_long(M.x86.R_EDI); + } + else { + u16 old_sp = M.x86.R_SP; + + push_word(M.x86.R_AX); + push_word(M.x86.R_CX); + push_word(M.x86.R_DX); + push_word(M.x86.R_BX); + push_word(old_sp); + push_word(M.x86.R_BP); + push_word(M.x86.R_SI); + push_word(M.x86.R_DI); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x61 +****************************************************************************/ +static void +x86emuOp_pop_all(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POPAD\n"); + } + else { + DECODE_PRINTF("POPA\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDI = pop_long(); + M.x86.R_ESI = pop_long(); + M.x86.R_EBP = pop_long(); + M.x86.R_ESP += 4; /* skip ESP */ + M.x86.R_EBX = pop_long(); + M.x86.R_EDX = pop_long(); + M.x86.R_ECX = pop_long(); + M.x86.R_EAX = pop_long(); + } + else { + M.x86.R_DI = pop_word(); + M.x86.R_SI = pop_word(); + M.x86.R_BP = pop_word(); + M.x86.R_SP += 2; /* skip SP */ + M.x86.R_BX = pop_word(); + M.x86.R_DX = pop_word(); + M.x86.R_CX = pop_word(); + M.x86.R_AX = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */ +/*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */ + +/**************************************************************************** +REMARKS: +Handles opcode 0x64 +****************************************************************************/ +static void +x86emuOp_segovr_FS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("FS:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_FS; + /* + * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 + * opcode subroutines we do not want to do this. + */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x65 +****************************************************************************/ +static void +x86emuOp_segovr_GS(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("GS:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_SEGOVR_GS; + /* + * note the lack of DECODE_CLEAR_SEGOVR(r) since, here is one of 4 + * opcode subroutines we do not want to do this. + */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x66 - prefix for 32-bit register +****************************************************************************/ +static void +x86emuOp_prefix_data(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("DATA:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_PREFIX_DATA; + /* note no DECODE_CLEAR_SEGOVR here. */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x67 - prefix for 32-bit address +****************************************************************************/ +static void +x86emuOp_prefix_addr(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("ADDR:\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_PREFIX_ADDR; + /* note no DECODE_CLEAR_SEGOVR here. */ + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x68 +****************************************************************************/ +static void +x86emuOp_push_word_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 imm; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + imm = fetch_long_imm(); + } + else { + imm = fetch_word_imm(); + } + DECODE_PRINTF2("PUSH\t%x\n", imm); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(imm); + } + else { + push_word((u16) imm); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x69 +****************************************************************************/ +static void +x86emuOp_imul_word_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("IMUL\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + s32 imm; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + s16 imm; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + s32 imm; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + s16 imm; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + s32 imm; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + s16 imm; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + u32 res_lo, res_hi; + s32 imm; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * srcreg, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg, *srcreg; + u32 res; + s16 imm; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + res = (s16) * srcreg * (s16) imm; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6a +****************************************************************************/ +static void +x86emuOp_push_byte_IMM(u8 X86EMU_UNUSED(op1)) +{ + s16 imm; + + START_OF_INSTR(); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2("PUSH\t%d\n", imm); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long((s32) imm); + } + else { + push_word(imm); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6b +****************************************************************************/ +static void +x86emuOp_imul_byte_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + s8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("IMUL\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) srcval, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + res = (s16) srcval *(s16) imm; + + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * srcreg, (s32) imm); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg, *srcreg; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%d\n", (s32) imm); + res = (s16) * srcreg * (s16) imm; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6c +****************************************************************************/ +static void +x86emuOp_ins_byte(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("INSB\n"); + ins(1); + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6d +****************************************************************************/ +static void +x86emuOp_ins_word(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INSD\n"); + ins(4); + } + else { + DECODE_PRINTF("INSW\n"); + ins(2); + } + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6e +****************************************************************************/ +static void +x86emuOp_outs_byte(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("OUTSB\n"); + outs(1); + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x6f +****************************************************************************/ +static void +x86emuOp_outs_word(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("OUTSD\n"); + outs(4); + } + else { + DECODE_PRINTF("OUTSW\n"); + outs(2); + } + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x70 +****************************************************************************/ +static void +x86emuOp_jump_near_O(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if overflow flag is set */ + START_OF_INSTR(); + DECODE_PRINTF("JO\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_OF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x71 +****************************************************************************/ +static void +x86emuOp_jump_near_NO(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if overflow is not set */ + START_OF_INSTR(); + DECODE_PRINTF("JNO\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!ACCESS_FLAG(F_OF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x72 +****************************************************************************/ +static void +x86emuOp_jump_near_B(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if carry flag is set. */ + START_OF_INSTR(); + DECODE_PRINTF("JB\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_CF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x73 +****************************************************************************/ +static void +x86emuOp_jump_near_NB(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if carry flag is clear. */ + START_OF_INSTR(); + DECODE_PRINTF("JNB\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!ACCESS_FLAG(F_CF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x74 +****************************************************************************/ +static void +x86emuOp_jump_near_Z(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if zero flag is set. */ + START_OF_INSTR(); + DECODE_PRINTF("JZ\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_ZF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x75 +****************************************************************************/ +static void +x86emuOp_jump_near_NZ(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if zero flag is clear. */ + START_OF_INSTR(); + DECODE_PRINTF("JNZ\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!ACCESS_FLAG(F_ZF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x76 +****************************************************************************/ +static void +x86emuOp_jump_near_BE(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if carry flag is set or if the zero + flag is set. */ + START_OF_INSTR(); + DECODE_PRINTF("JBE\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x77 +****************************************************************************/ +static void +x86emuOp_jump_near_NBE(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if carry flag is clear and if the zero + flag is clear */ + START_OF_INSTR(); + DECODE_PRINTF("JNBE\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF))) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x78 +****************************************************************************/ +static void +x86emuOp_jump_near_S(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if sign flag is set */ + START_OF_INSTR(); + DECODE_PRINTF("JS\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_SF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x79 +****************************************************************************/ +static void +x86emuOp_jump_near_NS(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if sign flag is clear */ + START_OF_INSTR(); + DECODE_PRINTF("JNS\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!ACCESS_FLAG(F_SF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7a +****************************************************************************/ +static void +x86emuOp_jump_near_P(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if parity flag is set (even parity) */ + START_OF_INSTR(); + DECODE_PRINTF("JP\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_PF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7b +****************************************************************************/ +static void +x86emuOp_jump_near_NP(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + + /* jump to byte offset if parity flag is clear (odd parity) */ + START_OF_INSTR(); + DECODE_PRINTF("JNP\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (!ACCESS_FLAG(F_PF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7c +****************************************************************************/ +static void +x86emuOp_jump_near_L(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + int sf, of; + + /* jump to byte offset if sign flag not equal to overflow flag. */ + START_OF_INSTR(); + DECODE_PRINTF("JL\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + sf = ACCESS_FLAG(F_SF) != 0; + of = ACCESS_FLAG(F_OF) != 0; + if (sf ^ of) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7d +****************************************************************************/ +static void +x86emuOp_jump_near_NL(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + int sf, of; + + /* jump to byte offset if sign flag not equal to overflow flag. */ + START_OF_INSTR(); + DECODE_PRINTF("JNL\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + sf = ACCESS_FLAG(F_SF) != 0; + of = ACCESS_FLAG(F_OF) != 0; + /* note: inverse of above, but using == instead of xor. */ + if (sf == of) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7e +****************************************************************************/ +static void +x86emuOp_jump_near_LE(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + int sf, of; + + /* jump to byte offset if sign flag not equal to overflow flag + or the zero flag is set */ + START_OF_INSTR(); + DECODE_PRINTF("JLE\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + sf = ACCESS_FLAG(F_SF) != 0; + of = ACCESS_FLAG(F_OF) != 0; + if ((sf ^ of) || ACCESS_FLAG(F_ZF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x7f +****************************************************************************/ +static void +x86emuOp_jump_near_NLE(u8 X86EMU_UNUSED(op1)) +{ + s8 offset; + u16 target; + int sf, of; + + /* jump to byte offset if sign flag equal to overflow flag. + and the zero flag is clear */ + START_OF_INSTR(); + DECODE_PRINTF("JNLE\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + (s16) offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + sf = ACCESS_FLAG(F_SF) != 0; + of = ACCESS_FLAG(F_OF) != 0; + if ((sf == of) && !ACCESS_FLAG(F_ZF)) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +static u8(*opc80_byte_operation[]) (u8 d, u8 s) = { + add_byte, /* 00 */ + or_byte, /* 01 */ + adc_byte, /* 02 */ + sbb_byte, /* 03 */ + and_byte, /* 04 */ + sub_byte, /* 05 */ + xor_byte, /* 06 */ + cmp_byte, /* 07 */ +}; + +/**************************************************************************** +REMARKS: +Handles opcode 0x80 +****************************************************************************/ +static void +x86emuOp_opc80_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 imm; + u8 destval; + + /* + * Weirdo special case instruction format. Part of the opcode + * held below in "RH". Doubly nested case would result, except + * that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + DECODE_PRINTF("ADD\t"); + break; + case 1: + DECODE_PRINTF("OR\t"); + break; + case 2: + DECODE_PRINTF("ADC\t"); + break; + case 3: + DECODE_PRINTF("SBB\t"); + break; + case 4: + DECODE_PRINTF("AND\t"); + break; + case 5: + DECODE_PRINTF("SUB\t"); + break; + case 6: + DECODE_PRINTF("XOR\t"); + break; + case 7: + DECODE_PRINTF("CMP\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc80_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc80_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc80_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc80_byte_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +static u16(*opc81_word_operation[]) (u16 d, u16 s) = { + add_word, /*00 */ + or_word, /*01 */ + adc_word, /*02 */ + sbb_word, /*03 */ + and_word, /*04 */ + sub_word, /*05 */ + xor_word, /*06 */ + cmp_word, /*07 */ +}; + +static u32(*opc81_long_operation[]) (u32 d, u32 s) = { + add_long, /*00 */ + or_long, /*01 */ + adc_long, /*02 */ + sbb_long, /*03 */ + and_long, /*04 */ + sub_long, /*05 */ + xor_long, /*06 */ + cmp_long, /*07 */ +}; + +/**************************************************************************** +REMARKS: +Handles opcode 0x81 +****************************************************************************/ +static void +x86emuOp_opc81_word_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + /* + * Weirdo special case instruction format. Part of the opcode + * held below in "RH". Doubly nested case would result, except + * that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + DECODE_PRINTF("ADD\t"); + break; + case 1: + DECODE_PRINTF("OR\t"); + break; + case 2: + DECODE_PRINTF("ADC\t"); + break; + case 3: + DECODE_PRINTF("SBB\t"); + break; + case 4: + DECODE_PRINTF("AND\t"); + break; + case 5: + DECODE_PRINTF("SUB\t"); + break; + case 6: + DECODE_PRINTF("XOR\t"); + break; + case 7: + DECODE_PRINTF("CMP\t"); + break; + } + } +#endif + /* + * Know operation, decode the mod byte to find the addressing + * mode. + */ + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + imm = fetch_long_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 destval, imm; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + imm = fetch_long_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_long_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + } + else { + u16 *destreg; + u16 destval, imm; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc81_word_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +static u8(*opc82_byte_operation[]) (u8 s, u8 d) = { + add_byte, /*00 */ + or_byte, /*01 *//*YYY UNUSED ???? */ + adc_byte, /*02 */ + sbb_byte, /*03 */ + and_byte, /*04 *//*YYY UNUSED ???? */ + sub_byte, /*05 */ + xor_byte, /*06 *//*YYY UNUSED ???? */ + cmp_byte, /*07 */ +}; + +/**************************************************************************** +REMARKS: +Handles opcode 0x82 +****************************************************************************/ +static void +x86emuOp_opc82_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 imm; + u8 destval; + + /* + * Weirdo special case instruction format. Part of the opcode + * held below in "RH". Doubly nested case would result, except + * that the decoded instruction Similar to opcode 81, except that + * the immediate byte is sign extended to a word length. + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ADD\t"); + break; + case 1: + DECODE_PRINTF("OR\t"); + break; + case 2: + DECODE_PRINTF("ADC\t"); + break; + case 3: + DECODE_PRINTF("SBB\t"); + break; + case 4: + DECODE_PRINTF("AND\t"); + break; + case 5: + DECODE_PRINTF("SUB\t"); + break; + case 6: + DECODE_PRINTF("XOR\t"); + break; + case 7: + DECODE_PRINTF("CMP\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc82_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc82_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + destval = fetch_data_byte(destoffset); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc82_byte_operation[rh]) (destval, imm); + if (rh != 7) + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc82_byte_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +static u16(*opc83_word_operation[]) (u16 s, u16 d) = { + add_word, /*00 */ + or_word, /*01 *//*YYY UNUSED ???? */ + adc_word, /*02 */ + sbb_word, /*03 */ + and_word, /*04 *//*YYY UNUSED ???? */ + sub_word, /*05 */ + xor_word, /*06 *//*YYY UNUSED ???? */ + cmp_word, /*07 */ +}; + +static u32(*opc83_long_operation[]) (u32 s, u32 d) = { + add_long, /*00 */ + or_long, /*01 *//*YYY UNUSED ???? */ + adc_long, /*02 */ + sbb_long, /*03 */ + and_long, /*04 *//*YYY UNUSED ???? */ + sub_long, /*05 */ + xor_long, /*06 *//*YYY UNUSED ???? */ + cmp_long, /*07 */ +}; + +/**************************************************************************** +REMARKS: +Handles opcode 0x83 +****************************************************************************/ +static void +x86emuOp_opc83_word_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + /* + * Weirdo special case instruction format. Part of the opcode + * held below in "RH". Doubly nested case would result, except + * that the decoded instruction Similar to opcode 81, except that + * the immediate byte is sign extended to a word length. + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ADD\t"); + break; + case 1: + DECODE_PRINTF("OR\t"); + break; + case 2: + DECODE_PRINTF("ADC\t"); + break; + case 3: + DECODE_PRINTF("SBB\t"); + break; + case 4: + DECODE_PRINTF("AND\t"); + break; + case 5: + DECODE_PRINTF("SUB\t"); + break; + case 6: + DECODE_PRINTF("XOR\t"); + break; + case 7: + DECODE_PRINTF("CMP\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + destval = fetch_data_long(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + destval = fetch_data_word(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + destval = fetch_data_long(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + destval = fetch_data_word(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + destval = fetch_data_long(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_long_operation[rh]) (destval, imm); + if (rh != 7) + store_data_long(destoffset, destval); + } + else { + u16 destval, imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm10_address(rl); + destval = fetch_data_word(destoffset); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_word_operation[rh]) (destval, imm); + if (rh != 7) + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 destval, imm; + + destreg = DECODE_RM_LONG_REGISTER(rl); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_long_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + } + else { + u16 *destreg; + u16 destval, imm; + + destreg = DECODE_RM_WORD_REGISTER(rl); + imm = (s8) fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + destval = (*opc83_word_operation[rh]) (*destreg, imm); + if (rh != 7) + *destreg = destval; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x84 +****************************************************************************/ +static void +x86emuOp_test_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + + START_OF_INSTR(); + DECODE_PRINTF("TEST\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_byte(destval, *srcreg); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_byte(destval, *srcreg); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_byte(destval, *srcreg); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_byte(*destreg, *srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x85 +****************************************************************************/ +static void +x86emuOp_test_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("TEST\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_word(destval, *srcreg); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_word(destval, *srcreg); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_long(destval, *srcreg); + } + else { + u16 destval; + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_word(destval, *srcreg); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_long(*destreg, *srcreg); + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + test_word(*destreg, *srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x86 +****************************************************************************/ +static void +x86emuOp_xchg_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + u8 destval; + u8 tmp; + + START_OF_INSTR(); + DECODE_PRINTF("XCHG\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_byte(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_byte(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_byte(destoffset); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = *destreg; + *destreg = tmp; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x87 +****************************************************************************/ +static void +x86emuOp_xchg_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("XCHG\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + u32 destval, tmp; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_long(destoffset, destval); + } + else { + u16 *srcreg; + u16 destval, tmp; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + u32 destval, tmp; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_long(destoffset, destval); + } + else { + u16 *srcreg; + u16 destval, tmp; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + u32 destval, tmp; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_long(destoffset); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_long(destoffset, destval); + } + else { + u16 *srcreg; + u16 destval, tmp; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + destval = fetch_data_word(destoffset); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = destval; + destval = tmp; + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + u32 tmp; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = *destreg; + *destreg = tmp; + } + else { + u16 *destreg, *srcreg; + u16 tmp; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + tmp = *srcreg; + *srcreg = *destreg; + *destreg = tmp; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x88 +****************************************************************************/ +static void +x86emuOp_mov_byte_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_byte(destoffset, *srcreg); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_byte(destoffset, *srcreg); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_byte(destoffset, *srcreg); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x89 +****************************************************************************/ +static void +x86emuOp_mov_word_RM_R(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u32 destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_long(destoffset, *srcreg); + } + else { + u16 *srcreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_word(destoffset, *srcreg); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_long(destoffset, *srcreg); + } + else { + u16 *srcreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_word(destoffset, *srcreg); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_long(destoffset, *srcreg); + } + else { + u16 *srcreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + store_data_word(destoffset, *srcreg); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8a +****************************************************************************/ +static void +x86emuOp_mov_byte_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg, *srcreg; + uint srcoffset; + u8 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 1: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 2: + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8b +****************************************************************************/ +static void +x86emuOp_mov_word_R_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + else { + u16 *destreg, *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8c +****************************************************************************/ +static void +x86emuOp_mov_word_RM_SR(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u16 *destreg, *srcreg; + uint destoffset; + u16 destval; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcreg = decode_rm_seg_register(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = *srcreg; + store_data_word(destoffset, destval); + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcreg = decode_rm_seg_register(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = *srcreg; + store_data_word(destoffset, destval); + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcreg = decode_rm_seg_register(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = *srcreg; + store_data_word(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcreg = decode_rm_seg_register(rh); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8d +****************************************************************************/ +static void +x86emuOp_lea_word_R_M(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LEA\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + u32 *srcreg = DECODE_RM_LONG_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u32) destoffset; + } + else { + u16 *srcreg = DECODE_RM_WORD_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u16) destoffset; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + u32 *srcreg = DECODE_RM_LONG_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u32) destoffset; + } + else { + u16 *srcreg = DECODE_RM_WORD_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u16) destoffset; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_ADDR) { + u32 *srcreg = DECODE_RM_LONG_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u32) destoffset; + } + else { + u16 *srcreg = DECODE_RM_WORD_REGISTER(rh); + + DECODE_PRINTF(","); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *srcreg = (u16) destoffset; + } + break; + case 3: /* register to register */ + /* undefined. Do nothing. */ + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8e +****************************************************************************/ +static void +x86emuOp_mov_word_SR_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u16 *destreg, *srcreg; + uint srcoffset; + u16 srcval; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = decode_rm_seg_register(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 1: + destreg = decode_rm_seg_register(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 2: + destreg = decode_rm_seg_register(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 3: /* register to register */ + destreg = decode_rm_seg_register(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + break; + } + /* + * Clean up, and reset all the R_xSP pointers to the correct + * locations. This is about 3x too much overhead (doing all the + * segreg ptrs when only one is needed, but this instruction + * *cannot* be that common, and this isn't too much work anyway. + */ + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x8f +****************************************************************************/ +static void +x86emuOp_pop_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("POP\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + if (rh != 0) { + DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); + HALT_SYS(); + } + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_long(); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_word(); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_long(); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_word(); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_long(); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + destval = pop_word(); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = pop_long(); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = pop_word(); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x90 +****************************************************************************/ +static void +x86emuOp_nop(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("NOP\n"); + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x91 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_CX(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,ECX\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,CX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_ECX; + M.x86.R_ECX = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_CX; + M.x86.R_CX = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x92 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_DX(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,EDX\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,DX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_EDX; + M.x86.R_EDX = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_DX; + M.x86.R_DX = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x93 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_BX(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,EBX\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,BX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_EBX; + M.x86.R_EBX = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_BX; + M.x86.R_BX = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x94 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_SP(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,ESP\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,SP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_ESP; + M.x86.R_ESP = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_SP; + M.x86.R_SP = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x95 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_BP(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,EBP\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,BP\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_EBP; + M.x86.R_EBP = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_BP; + M.x86.R_BP = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x96 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_SI(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,ESI\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,SI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_ESI; + M.x86.R_ESI = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_SI; + M.x86.R_SI = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x97 +****************************************************************************/ +static void +x86emuOp_xchg_word_AX_DI(u8 X86EMU_UNUSED(op1)) +{ + u32 tmp; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("XCHG\tEAX,EDI\n"); + } + else { + DECODE_PRINTF("XCHG\tAX,DI\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + tmp = M.x86.R_EAX; + M.x86.R_EAX = M.x86.R_EDI; + M.x86.R_EDI = tmp; + } + else { + tmp = M.x86.R_AX; + M.x86.R_AX = M.x86.R_DI; + M.x86.R_DI = (u16) tmp; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x98 +****************************************************************************/ +static void +x86emuOp_cbw(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("CWDE\n"); + } + else { + DECODE_PRINTF("CBW\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + if (M.x86.R_AX & 0x8000) { + M.x86.R_EAX |= 0xffff0000; + } + else { + M.x86.R_EAX &= 0x0000ffff; + } + } + else { + if (M.x86.R_AL & 0x80) { + M.x86.R_AH = 0xff; + } + else { + M.x86.R_AH = 0x0; + } + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x99 +****************************************************************************/ +static void +x86emuOp_cwd(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("CDQ\n"); + } + else { + DECODE_PRINTF("CWD\n"); + } + DECODE_PRINTF("CWD\n"); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + if (M.x86.R_EAX & 0x80000000) { + M.x86.R_EDX = 0xffffffff; + } + else { + M.x86.R_EDX = 0x0; + } + } + else { + if (M.x86.R_AX & 0x8000) { + M.x86.R_DX = 0xffff; + } + else { + M.x86.R_DX = 0x0; + } + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9a +****************************************************************************/ +static void +x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 farseg, faroff; + + START_OF_INSTR(); + DECODE_PRINTF("CALL\t"); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + faroff = fetch_long_imm(); + farseg = fetch_word_imm(); + } + else { + faroff = fetch_word_imm(); + farseg = fetch_word_imm(); + } + DECODE_PRINTF2("%04x:", farseg); + DECODE_PRINTF2("%04x\n", faroff); + CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR "); + + /* XXX + * + * Hooked interrupt vectors calling into our "BIOS" will cause + * problems unless all intersegment stuff is checked for BIOS + * access. Check needed here. For moment, let it alone. + */ + TRACE_AND_STEP(); + push_word(M.x86.R_CS); + M.x86.R_CS = farseg; + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EIP); + } + else { + push_word(M.x86.R_IP); + } + M.x86.R_EIP = faroff & 0xffff; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9b +****************************************************************************/ +static void +x86emuOp_wait(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("WAIT"); + TRACE_AND_STEP(); + /* NADA. */ + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9c +****************************************************************************/ +static void +x86emuOp_pushf_word(u8 X86EMU_UNUSED(op1)) +{ + u32 flags; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("PUSHFD\n"); + } + else { + DECODE_PRINTF("PUSHF\n"); + } + TRACE_AND_STEP(); + + /* clear out *all* bits not representing flags, and turn on real bits */ + flags = (M.x86.R_EFLG & F_MSK) | F_ALWAYS_ON; + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(flags); + } + else { + push_word((u16) flags); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9d +****************************************************************************/ +static void +x86emuOp_popf_word(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("POPFD\n"); + } + else { + DECODE_PRINTF("POPF\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EFLG = pop_long(); + } + else { + M.x86.R_FLG = pop_word(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9e +****************************************************************************/ +static void +x86emuOp_sahf(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("SAHF\n"); + TRACE_AND_STEP(); + /* clear the lower bits of the flag register */ + M.x86.R_FLG &= 0xffffff00; + /* or in the AH register into the flags register */ + M.x86.R_FLG |= M.x86.R_AH; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x9f +****************************************************************************/ +static void +x86emuOp_lahf(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("LAHF\n"); + TRACE_AND_STEP(); + M.x86.R_AH = (u8) (M.x86.R_FLG & 0xff); + /*undocumented TC++ behavior??? Nope. It's documented, but + you have too look real hard to notice it. */ + M.x86.R_AH |= 0x2; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa0 +****************************************************************************/ +static void +x86emuOp_mov_AL_M_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 offset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tAL,"); + offset = fetch_word_imm(); + DECODE_PRINTF2("[%04x]\n", offset); + TRACE_AND_STEP(); + M.x86.R_AL = fetch_data_byte(offset); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa1 +****************************************************************************/ +static void +x86emuOp_mov_AX_M_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 offset; + + START_OF_INSTR(); + offset = fetch_word_imm(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF2("MOV\tEAX,[%04x]\n", offset); + } + else { + DECODE_PRINTF2("MOV\tAX,[%04x]\n", offset); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = fetch_data_long(offset); + } + else { + M.x86.R_AX = fetch_data_word(offset); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa2 +****************************************************************************/ +static void +x86emuOp_mov_M_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 offset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + offset = fetch_word_imm(); + DECODE_PRINTF2("[%04x],AL\n", offset); + TRACE_AND_STEP(); + store_data_byte(offset, M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa3 +****************************************************************************/ +static void +x86emuOp_mov_M_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 offset; + + START_OF_INSTR(); + offset = fetch_word_imm(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF2("MOV\t[%04x],EAX\n", offset); + } + else { + DECODE_PRINTF2("MOV\t[%04x],AX\n", offset); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + store_data_long(offset, M.x86.R_EAX); + } + else { + store_data_word(offset, M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa4 +****************************************************************************/ +static void +x86emuOp_movs_byte(u8 X86EMU_UNUSED(op1)) +{ + u8 val; + u32 count; + int inc; + + START_OF_INSTR(); + DECODE_PRINTF("MOVS\tBYTE\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -1; + else + inc = 1; + TRACE_AND_STEP(); + count = 1; + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + count = M.x86.R_CX; + M.x86.R_CX = 0; + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + while (count--) { + val = fetch_data_byte(M.x86.R_SI); + store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, val); + M.x86.R_SI += inc; + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa5 +****************************************************************************/ +static void +x86emuOp_movs_word(u8 X86EMU_UNUSED(op1)) +{ + u32 val; + int inc; + u32 count; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOVS\tDWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -4; + else + inc = 4; + } + else { + DECODE_PRINTF("MOVS\tWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -2; + else + inc = 2; + } + TRACE_AND_STEP(); + count = 1; + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + count = M.x86.R_CX; + M.x86.R_CX = 0; + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + while (count--) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val = fetch_data_long(M.x86.R_SI); + store_data_long_abs(M.x86.R_ES, M.x86.R_DI, val); + } + else { + val = fetch_data_word(M.x86.R_SI); + store_data_word_abs(M.x86.R_ES, M.x86.R_DI, (u16) val); + } + M.x86.R_SI += inc; + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa6 +****************************************************************************/ +static void +x86emuOp_cmps_byte(u8 X86EMU_UNUSED(op1)) +{ + s8 val1, val2; + int inc; + + START_OF_INSTR(); + DECODE_PRINTF("CMPS\tBYTE\n"); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -1; + else + inc = 1; + + if (M.x86.mode & SYSMODE_PREFIX_REPE) { + /* REPE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + val1 = fetch_data_byte(M.x86.R_SI); + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(val1, val2); + M.x86.R_CX -= 1; + M.x86.R_SI += inc; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF) == 0) + break; + } + M.x86.mode &= ~SYSMODE_PREFIX_REPE; + } + else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { + /* REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + val1 = fetch_data_byte(M.x86.R_SI); + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(val1, val2); + M.x86.R_CX -= 1; + M.x86.R_SI += inc; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF)) + break; /* zero flag set means equal */ + } + M.x86.mode &= ~SYSMODE_PREFIX_REPNE; + } + else { + val1 = fetch_data_byte(M.x86.R_SI); + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(val1, val2); + M.x86.R_SI += inc; + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa7 +****************************************************************************/ +static void +x86emuOp_cmps_word(u8 X86EMU_UNUSED(op1)) +{ + u32 val1, val2; + int inc; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("CMPS\tDWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -4; + else + inc = 4; + } + else { + DECODE_PRINTF("CMPS\tWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -2; + else + inc = 2; + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_REPE) { + /* REPE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val1 = fetch_data_long(M.x86.R_SI); + val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(val1, val2); + } + else { + val1 = fetch_data_word(M.x86.R_SI); + val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word((u16) val1, (u16) val2); + } + M.x86.R_CX -= 1; + M.x86.R_SI += inc; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF) == 0) + break; + } + M.x86.mode &= ~SYSMODE_PREFIX_REPE; + } + else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { + /* REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val1 = fetch_data_long(M.x86.R_SI); + val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(val1, val2); + } + else { + val1 = fetch_data_word(M.x86.R_SI); + val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word((u16) val1, (u16) val2); + } + M.x86.R_CX -= 1; + M.x86.R_SI += inc; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF)) + break; /* zero flag set means equal */ + } + M.x86.mode &= ~SYSMODE_PREFIX_REPNE; + } + else { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val1 = fetch_data_long(M.x86.R_SI); + val2 = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(val1, val2); + } + else { + val1 = fetch_data_word(M.x86.R_SI); + val2 = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word((u16) val1, (u16) val2); + } + M.x86.R_SI += inc; + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa8 +****************************************************************************/ +static void +x86emuOp_test_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + int imm; + + START_OF_INSTR(); + DECODE_PRINTF("TEST\tAL,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%04x\n", imm); + TRACE_AND_STEP(); + test_byte(M.x86.R_AL, (u8) imm); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xa9 +****************************************************************************/ +static void +x86emuOp_test_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("TEST\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("TEST\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + test_long(M.x86.R_EAX, srcval); + } + else { + test_word(M.x86.R_AX, (u16) srcval); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xaa +****************************************************************************/ +static void +x86emuOp_stos_byte(u8 X86EMU_UNUSED(op1)) +{ + int inc; + + START_OF_INSTR(); + DECODE_PRINTF("STOS\tBYTE\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -1; + else + inc = 1; + TRACE_AND_STEP(); + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); + M.x86.R_CX -= 1; + M.x86.R_DI += inc; + } + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + else { + store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AL); + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xab +****************************************************************************/ +static void +x86emuOp_stos_word(u8 X86EMU_UNUSED(op1)) +{ + int inc; + u32 count; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("STOS\tDWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -4; + else + inc = 4; + } + else { + DECODE_PRINTF("STOS\tWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -2; + else + inc = 2; + } + TRACE_AND_STEP(); + count = 1; + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + count = M.x86.R_CX; + M.x86.R_CX = 0; + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + while (count--) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + store_data_long_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_EAX); + } + else { + store_data_word_abs(M.x86.R_ES, M.x86.R_DI, M.x86.R_AX); + } + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xac +****************************************************************************/ +static void +x86emuOp_lods_byte(u8 X86EMU_UNUSED(op1)) +{ + int inc; + + START_OF_INSTR(); + DECODE_PRINTF("LODS\tBYTE\n"); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -1; + else + inc = 1; + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + M.x86.R_AL = fetch_data_byte(M.x86.R_SI); + M.x86.R_CX -= 1; + M.x86.R_SI += inc; + } + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + else { + M.x86.R_AL = fetch_data_byte(M.x86.R_SI); + M.x86.R_SI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xad +****************************************************************************/ +static void +x86emuOp_lods_word(u8 X86EMU_UNUSED(op1)) +{ + int inc; + u32 count; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("LODS\tDWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -4; + else + inc = 4; + } + else { + DECODE_PRINTF("LODS\tWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -2; + else + inc = 2; + } + TRACE_AND_STEP(); + count = 1; + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* move them until CX is ZERO. */ + count = M.x86.R_CX; + M.x86.R_CX = 0; + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + while (count--) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = fetch_data_long(M.x86.R_SI); + } + else { + M.x86.R_AX = fetch_data_word(M.x86.R_SI); + } + M.x86.R_SI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xae +****************************************************************************/ +static void +x86emuOp_scas_byte(u8 X86EMU_UNUSED(op1)) +{ + s8 val2; + int inc; + + START_OF_INSTR(); + DECODE_PRINTF("SCAS\tBYTE\n"); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -1; + else + inc = 1; + if (M.x86.mode & SYSMODE_PREFIX_REPE) { + /* REPE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(M.x86.R_AL, val2); + M.x86.R_CX -= 1; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF) == 0) + break; + } + M.x86.mode &= ~SYSMODE_PREFIX_REPE; + } + else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { + /* REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(M.x86.R_AL, val2); + M.x86.R_CX -= 1; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF)) + break; /* zero flag set means equal */ + } + M.x86.mode &= ~SYSMODE_PREFIX_REPNE; + } + else { + val2 = fetch_data_byte_abs(M.x86.R_ES, M.x86.R_DI); + cmp_byte(M.x86.R_AL, val2); + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xaf +****************************************************************************/ +static void +x86emuOp_scas_word(u8 X86EMU_UNUSED(op1)) +{ + int inc; + u32 val; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("SCAS\tDWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -4; + else + inc = 4; + } + else { + DECODE_PRINTF("SCAS\tWORD\n"); + if (ACCESS_FLAG(F_DF)) /* down */ + inc = -2; + else + inc = 2; + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_REPE) { + /* REPE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(M.x86.R_EAX, val); + } + else { + val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word(M.x86.R_AX, (u16) val); + } + M.x86.R_CX -= 1; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF) == 0) + break; + } + M.x86.mode &= ~SYSMODE_PREFIX_REPE; + } + else if (M.x86.mode & SYSMODE_PREFIX_REPNE) { + /* REPNE */ + /* move them until CX is ZERO. */ + while (M.x86.R_CX != 0) { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(M.x86.R_EAX, val); + } + else { + val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word(M.x86.R_AX, (u16) val); + } + M.x86.R_CX -= 1; + M.x86.R_DI += inc; + if (ACCESS_FLAG(F_ZF)) + break; /* zero flag set means equal */ + } + M.x86.mode &= ~SYSMODE_PREFIX_REPNE; + } + else { + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + val = fetch_data_long_abs(M.x86.R_ES, M.x86.R_DI); + cmp_long(M.x86.R_EAX, val); + } + else { + val = fetch_data_word_abs(M.x86.R_ES, M.x86.R_DI); + cmp_word(M.x86.R_AX, (u16) val); + } + M.x86.R_DI += inc; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb0 +****************************************************************************/ +static void +x86emuOp_mov_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tAL,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_AL = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb1 +****************************************************************************/ +static void +x86emuOp_mov_byte_CL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tCL,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_CL = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb2 +****************************************************************************/ +static void +x86emuOp_mov_byte_DL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tDL,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_DL = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb3 +****************************************************************************/ +static void +x86emuOp_mov_byte_BL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tBL,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_BL = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb4 +****************************************************************************/ +static void +x86emuOp_mov_byte_AH_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tAH,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_AH = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb5 +****************************************************************************/ +static void +x86emuOp_mov_byte_CH_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tCH,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_CH = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb6 +****************************************************************************/ +static void +x86emuOp_mov_byte_DH_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tDH,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_DH = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb7 +****************************************************************************/ +static void +x86emuOp_mov_byte_BH_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\tBH,"); + imm = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", imm); + TRACE_AND_STEP(); + M.x86.R_BH = imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb8 +****************************************************************************/ +static void +x86emuOp_mov_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tEAX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tAX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = srcval; + } + else { + M.x86.R_AX = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xb9 +****************************************************************************/ +static void +x86emuOp_mov_word_CX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tECX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tCX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = srcval; + } + else { + M.x86.R_CX = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xba +****************************************************************************/ +static void +x86emuOp_mov_word_DX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tEDX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tDX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDX = srcval; + } + else { + M.x86.R_DX = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xbb +****************************************************************************/ +static void +x86emuOp_mov_word_BX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tEBX,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tBX,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBX = srcval; + } + else { + M.x86.R_BX = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xbc +****************************************************************************/ +static void +x86emuOp_mov_word_SP_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tESP,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tSP,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESP = srcval; + } + else { + M.x86.R_SP = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xbd +****************************************************************************/ +static void +x86emuOp_mov_word_BP_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tEBP,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tBP,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EBP = srcval; + } + else { + M.x86.R_BP = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xbe +****************************************************************************/ +static void +x86emuOp_mov_word_SI_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tESI,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tSI,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ESI = srcval; + } + else { + M.x86.R_SI = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xbf +****************************************************************************/ +static void +x86emuOp_mov_word_DI_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 srcval; + + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("MOV\tEDI,"); + srcval = fetch_long_imm(); + } + else { + DECODE_PRINTF("MOV\tDI,"); + srcval = fetch_word_imm(); + } + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EDI = srcval; + } + else { + M.x86.R_DI = (u16) srcval; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/* used by opcodes c0, d0, and d2. */ +static u8(*opcD0_byte_operation[]) (u8 d, u8 s) = { + rol_byte, ror_byte, rcl_byte, rcr_byte, shl_byte, shr_byte, shl_byte, /* sal_byte === shl_byte by definition */ +sar_byte,}; + +/**************************************************************************** +REMARKS: +Handles opcode 0xc0 +****************************************************************************/ +static void +x86emuOp_opcC0_byte_RM_MEM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 destval; + u8 amt; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (*destreg, amt); + *destreg = destval; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/* used by opcodes c1, d1, and d3. */ +static u16(*opcD1_word_operation[]) (u16 s, u8 d) = { + rol_word, ror_word, rcl_word, rcr_word, shl_word, shr_word, shl_word, /* sal_byte === shl_byte by definition */ +sar_word,}; + +/* used by opcodes c1, d1, and d3. */ +static u32(*opcD1_long_operation[]) (u32 s, u8 d) = { + rol_long, ror_long, rcl_long, rcr_long, shl_long, shr_long, shl_long, /* sal_byte === shl_byte by definition */ +sar_long,}; + +/**************************************************************************** +REMARKS: +Handles opcode 0xc1 +****************************************************************************/ +static void +x86emuOp_opcC1_word_RM_MEM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + u8 amt; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm10_address(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + TRACE_AND_STEP(); + *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + amt = fetch_byte_imm(); + DECODE_PRINTF2(",%x\n", amt); + TRACE_AND_STEP(); + *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc2 +****************************************************************************/ +static void +x86emuOp_ret_near_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 imm; + + START_OF_INSTR(); + DECODE_PRINTF("RET\t"); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + RETURN_TRACE("RET", M.x86.saved_cs, M.x86.saved_ip); + TRACE_AND_STEP(); + M.x86.R_IP = pop_word(); + M.x86.R_SP += imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc3 +****************************************************************************/ +static void +x86emuOp_ret_near(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("RET\n"); + RETURN_TRACE("RET", M.x86.saved_cs, M.x86.saved_ip); + TRACE_AND_STEP(); + M.x86.R_IP = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc4 +****************************************************************************/ +static void +x86emuOp_les_R_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rh, rl; + u16 *dstreg; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LES\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_ES = fetch_data_word(srcoffset + 2); + break; + case 1: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_ES = fetch_data_word(srcoffset + 2); + break; + case 2: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_ES = fetch_data_word(srcoffset + 2); + break; + case 3: /* register to register */ + /* UNDEFINED! */ + TRACE_AND_STEP(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc5 +****************************************************************************/ +static void +x86emuOp_lds_R_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rh, rl; + u16 *dstreg; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LDS\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_DS = fetch_data_word(srcoffset + 2); + break; + case 1: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_DS = fetch_data_word(srcoffset + 2); + break; + case 2: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_DS = fetch_data_word(srcoffset + 2); + break; + case 3: /* register to register */ + /* UNDEFINED! */ + TRACE_AND_STEP(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc6 +****************************************************************************/ +static void +x86emuOp_mov_byte_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 imm; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + if (rh != 0) { + DECODE_PRINTF("ILLEGAL DECODE OF OPCODE c6\n"); + HALT_SYS(); + } + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%2x\n", imm); + TRACE_AND_STEP(); + store_data_byte(destoffset, imm); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%2x\n", imm); + TRACE_AND_STEP(); + store_data_byte(destoffset, imm); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%2x\n", imm); + TRACE_AND_STEP(); + store_data_byte(destoffset, imm); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + imm = fetch_byte_imm(); + DECODE_PRINTF2(",%2x\n", imm); + TRACE_AND_STEP(); + *destreg = imm; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc7 +****************************************************************************/ +static void +x86emuOp_mov_word_RM_IMM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOV\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + if (rh != 0) { + DECODE_PRINTF("ILLEGAL DECODE OF OPCODE 8F\n"); + HALT_SYS(); + } + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_long(destoffset, imm); + } + else { + u16 imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_word(destoffset, imm); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_long(destoffset, imm); + } + else { + u16 imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_word(destoffset, imm); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 imm; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_long(destoffset, imm); + } + else { + u16 imm; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm10_address(rl); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + store_data_word(destoffset, imm); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 imm; + + destreg = DECODE_RM_LONG_REGISTER(rl); + imm = fetch_long_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + *destreg = imm; + } + else { + u16 *destreg; + u16 imm; + + destreg = DECODE_RM_WORD_REGISTER(rl); + imm = fetch_word_imm(); + DECODE_PRINTF2(",%x\n", imm); + TRACE_AND_STEP(); + *destreg = imm; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc8 +****************************************************************************/ +static void +x86emuOp_enter(u8 X86EMU_UNUSED(op1)) +{ + u16 local, frame_pointer; + u8 nesting; + int i; + + START_OF_INSTR(); + local = fetch_word_imm(); + nesting = fetch_byte_imm(); + DECODE_PRINTF2("ENTER %x\n", local); + DECODE_PRINTF2(",%x\n", nesting); + TRACE_AND_STEP(); + push_word(M.x86.R_BP); + frame_pointer = M.x86.R_SP; + if (nesting > 0) { + for (i = 1; i < nesting; i++) { + M.x86.R_BP -= 2; + push_word(fetch_data_word_abs(M.x86.R_SS, M.x86.R_BP)); + } + push_word(frame_pointer); + } + M.x86.R_BP = frame_pointer; + M.x86.R_SP = (u16) (M.x86.R_SP - local); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xc9 +****************************************************************************/ +static void +x86emuOp_leave(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("LEAVE\n"); + TRACE_AND_STEP(); + M.x86.R_SP = M.x86.R_BP; + M.x86.R_BP = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xca +****************************************************************************/ +static void +x86emuOp_ret_far_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 imm; + + START_OF_INSTR(); + DECODE_PRINTF("RETF\t"); + imm = fetch_word_imm(); + DECODE_PRINTF2("%x\n", imm); + RETURN_TRACE("RETF", M.x86.saved_cs, M.x86.saved_ip); + TRACE_AND_STEP(); + M.x86.R_IP = pop_word(); + M.x86.R_CS = pop_word(); + M.x86.R_SP += imm; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xcb +****************************************************************************/ +static void +x86emuOp_ret_far(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("RETF\n"); + RETURN_TRACE("RETF", M.x86.saved_cs, M.x86.saved_ip); + TRACE_AND_STEP(); + M.x86.R_IP = pop_word(); + M.x86.R_CS = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xcc +****************************************************************************/ +static void +x86emuOp_int3(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("INT 3\n"); + TRACE_AND_STEP(); + if (_X86EMU_intrTab[3]) { + (*_X86EMU_intrTab[3]) (3); + } + else { + push_word((u16) M.x86.R_FLG); + CLEAR_FLAG(F_IF); + CLEAR_FLAG(F_TF); + push_word(M.x86.R_CS); + M.x86.R_CS = mem_access_word(3 * 4 + 2); + push_word(M.x86.R_IP); + M.x86.R_IP = mem_access_word(3 * 4); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xcd +****************************************************************************/ +static void +x86emuOp_int_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 intnum; + + START_OF_INSTR(); + DECODE_PRINTF("INT\t"); + intnum = fetch_byte_imm(); + DECODE_PRINTF2("%x\n", intnum); + TRACE_AND_STEP(); + if (_X86EMU_intrTab[intnum]) { + (*_X86EMU_intrTab[intnum]) (intnum); + } + else { + push_word((u16) M.x86.R_FLG); + CLEAR_FLAG(F_IF); + CLEAR_FLAG(F_TF); + push_word(M.x86.R_CS); + M.x86.R_CS = mem_access_word(intnum * 4 + 2); + push_word(M.x86.R_IP); + M.x86.R_IP = mem_access_word(intnum * 4); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xce +****************************************************************************/ +static void +x86emuOp_into(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("INTO\n"); + TRACE_AND_STEP(); + if (ACCESS_FLAG(F_OF)) { + if (_X86EMU_intrTab[4]) { + (*_X86EMU_intrTab[4]) (4); + } + else { + push_word((u16) M.x86.R_FLG); + CLEAR_FLAG(F_IF); + CLEAR_FLAG(F_TF); + push_word(M.x86.R_CS); + M.x86.R_CS = mem_access_word(4 * 4 + 2); + push_word(M.x86.R_IP); + M.x86.R_IP = mem_access_word(4 * 4); + } + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xcf +****************************************************************************/ +static void +x86emuOp_iret(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("IRET\n"); + + TRACE_AND_STEP(); + + M.x86.R_IP = pop_word(); + M.x86.R_CS = pop_word(); + M.x86.R_FLG = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd0 +****************************************************************************/ +static void +x86emuOp_opcD0_byte_RM_1(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 destval; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, 1); + store_data_byte(destoffset, destval); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, 1); + store_data_byte(destoffset, destval); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, 1); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(",1\n"); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (*destreg, 1); + *destreg = destval; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd1 +****************************************************************************/ +static void +x86emuOp_opcD1_word_RM_1(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, 1); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, 1); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, 1); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, 1); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, 1); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",1\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, 1); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(",1\n"); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (*destreg, 1); + *destreg = destval; + } + else { + u16 destval; + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(",1\n"); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (*destreg, 1); + *destreg = destval; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd2 +****************************************************************************/ +static void +x86emuOp_opcD2_byte_RM_CL(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 destval; + u8 amt; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + amt = M.x86.R_CL; + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (destval, amt); + store_data_byte(destoffset, destval); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = (*opcD0_byte_operation[rh]) (*destreg, amt); + *destreg = destval; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd3 +****************************************************************************/ +static void +x86emuOp_opcD3_word_RM_CL(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + u8 amt; + + /* + * Yet another weirdo special case instruction format. Part of + * the opcode held below in "RH". Doubly nested case would + * result, except that the decoded instruction + */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + switch (rh) { + case 0: + DECODE_PRINTF("ROL\t"); + break; + case 1: + DECODE_PRINTF("ROR\t"); + break; + case 2: + DECODE_PRINTF("RCL\t"); + break; + case 3: + DECODE_PRINTF("RCR\t"); + break; + case 4: + DECODE_PRINTF("SHL\t"); + break; + case 5: + DECODE_PRINTF("SHR\t"); + break; + case 6: + DECODE_PRINTF("SAL\t"); + break; + case 7: + DECODE_PRINTF("SAR\t"); + break; + } + } +#endif + /* know operation, decode the mod byte to find the addressing + mode. */ + amt = M.x86.R_CL; + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_long_operation[rh]) (destval, amt); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("WORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(",CL\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = (*opcD1_word_operation[rh]) (destval, amt); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = (*opcD1_long_operation[rh]) (*destreg, amt); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = (*opcD1_word_operation[rh]) (*destreg, amt); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd4 +****************************************************************************/ +static void +x86emuOp_aam(u8 X86EMU_UNUSED(op1)) +{ + u8 a; + + START_OF_INSTR(); + DECODE_PRINTF("AAM\n"); + a = fetch_byte_imm(); /* this is a stupid encoding. */ + if (a != 10) { + /* fix: add base decoding + aam_word(u8 val, int base a) */ + DECODE_PRINTF("ERROR DECODING AAM\n"); + TRACE_REGS(); + HALT_SYS(); + } + TRACE_AND_STEP(); + /* note the type change here --- returning AL and AH in AX. */ + M.x86.R_AX = aam_word(M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xd5 +****************************************************************************/ +static void +x86emuOp_aad(u8 X86EMU_UNUSED(op1)) +{ + u8 a; + + START_OF_INSTR(); + DECODE_PRINTF("AAD\n"); + a = fetch_byte_imm(); + if (a != 10) { + /* fix: add base decoding + aad_word(u16 val, int base a) */ + DECODE_PRINTF("ERROR DECODING AAM\n"); + TRACE_REGS(); + HALT_SYS(); + } + TRACE_AND_STEP(); + M.x86.R_AX = aad_word(M.x86.R_AX); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/* opcode 0xd6 ILLEGAL OPCODE */ + +/**************************************************************************** +REMARKS: +Handles opcode 0xd7 +****************************************************************************/ +static void +x86emuOp_xlat(u8 X86EMU_UNUSED(op1)) +{ + u16 addr; + + START_OF_INSTR(); + DECODE_PRINTF("XLAT\n"); + TRACE_AND_STEP(); + addr = (u16) (M.x86.R_BX + (u8) M.x86.R_AL); + M.x86.R_AL = fetch_data_byte(addr); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/* instuctions D8 .. DF are in i87_ops.c */ + +/**************************************************************************** +REMARKS: +Handles opcode 0xe0 +****************************************************************************/ +static void +x86emuOp_loopne(u8 X86EMU_UNUSED(op1)) +{ + s16 ip; + + START_OF_INSTR(); + DECODE_PRINTF("LOOPNE\t"); + ip = (s8) fetch_byte_imm(); + ip += (s16) M.x86.R_IP; + DECODE_PRINTF2("%04x\n", ip); + TRACE_AND_STEP(); + M.x86.R_CX -= 1; + if (M.x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */ + M.x86.R_IP = ip; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe1 +****************************************************************************/ +static void +x86emuOp_loope(u8 X86EMU_UNUSED(op1)) +{ + s16 ip; + + START_OF_INSTR(); + DECODE_PRINTF("LOOPE\t"); + ip = (s8) fetch_byte_imm(); + ip += (s16) M.x86.R_IP; + DECODE_PRINTF2("%04x\n", ip); + TRACE_AND_STEP(); + M.x86.R_CX -= 1; + if (M.x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */ + M.x86.R_IP = ip; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe2 +****************************************************************************/ +static void +x86emuOp_loop(u8 X86EMU_UNUSED(op1)) +{ + s16 ip; + + START_OF_INSTR(); + DECODE_PRINTF("LOOP\t"); + ip = (s8) fetch_byte_imm(); + ip += (s16) M.x86.R_IP; + DECODE_PRINTF2("%04x\n", ip); + TRACE_AND_STEP(); + M.x86.R_CX -= 1; + if (M.x86.R_CX != 0) + M.x86.R_IP = ip; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe3 +****************************************************************************/ +static void +x86emuOp_jcxz(u8 X86EMU_UNUSED(op1)) +{ + u16 target; + s8 offset; + + /* jump to byte offset if overflow flag is set */ + START_OF_INSTR(); + DECODE_PRINTF("JCXZ\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + if (M.x86.R_CX == 0) + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe4 +****************************************************************************/ +static void +x86emuOp_in_byte_AL_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 port; + + START_OF_INSTR(); + DECODE_PRINTF("IN\t"); + port = (u8) fetch_byte_imm(); + DECODE_PRINTF2("%x,AL\n", port); + TRACE_AND_STEP(); + M.x86.R_AL = (*sys_inb) (port); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe5 +****************************************************************************/ +static void +x86emuOp_in_word_AX_IMM(u8 X86EMU_UNUSED(op1)) +{ + u8 port; + + START_OF_INSTR(); + DECODE_PRINTF("IN\t"); + port = (u8) fetch_byte_imm(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF2("EAX,%x\n", port); + } + else { + DECODE_PRINTF2("AX,%x\n", port); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = (*sys_inl) (port); + } + else { + M.x86.R_AX = (*sys_inw) (port); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe6 +****************************************************************************/ +static void +x86emuOp_out_byte_IMM_AL(u8 X86EMU_UNUSED(op1)) +{ + u8 port; + + START_OF_INSTR(); + DECODE_PRINTF("OUT\t"); + port = (u8) fetch_byte_imm(); + DECODE_PRINTF2("%x,AL\n", port); + TRACE_AND_STEP(); + (*sys_outb) (port, M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe7 +****************************************************************************/ +static void +x86emuOp_out_word_IMM_AX(u8 X86EMU_UNUSED(op1)) +{ + u8 port; + + START_OF_INSTR(); + DECODE_PRINTF("OUT\t"); + port = (u8) fetch_byte_imm(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF2("%x,EAX\n", port); + } + else { + DECODE_PRINTF2("%x,AX\n", port); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + (*sys_outl) (port, M.x86.R_EAX); + } + else { + (*sys_outw) (port, M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe8 +****************************************************************************/ +static void +x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) +{ + s16 ip16; + s32 ip32; + + START_OF_INSTR(); + DECODE_PRINTF("CALL\t"); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + ip32 = (s32) fetch_long_imm(); + ip32 += (s16) M.x86.R_IP; /* CHECK SIGN */ + DECODE_PRINTF2("%04x\n", (u16) ip32); + CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip32, ""); + } + else { + ip16 = (s16) fetch_word_imm(); + ip16 += (s16) M.x86.R_IP; /* CHECK SIGN */ + DECODE_PRINTF2("%04x\n", (u16) ip16); + CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip16, ""); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + push_long(M.x86.R_EIP); + M.x86.R_EIP = ip32 & 0xffff; + } + else { + push_word(M.x86.R_IP); + M.x86.R_EIP = ip16; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xe9 +****************************************************************************/ +static void +x86emuOp_jump_near_IMM(u8 X86EMU_UNUSED(op1)) +{ + u32 ip; + + START_OF_INSTR(); + DECODE_PRINTF("JMP\t"); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + ip = (u32) fetch_long_imm(); + ip += (u32) M.x86.R_EIP; + DECODE_PRINTF2("%08x\n", (u32) ip); + TRACE_AND_STEP(); + M.x86.R_EIP = (u32) ip; + } + else { + ip = (s16) fetch_word_imm(); + ip += (s16) M.x86.R_IP; + DECODE_PRINTF2("%04x\n", (u16) ip); + TRACE_AND_STEP(); + M.x86.R_IP = (u16) ip; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xea +****************************************************************************/ +static void +x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 cs; + u32 ip; + + START_OF_INSTR(); + DECODE_PRINTF("JMP\tFAR "); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + ip = fetch_long_imm(); + } + else { + ip = fetch_word_imm(); + } + cs = fetch_word_imm(); + DECODE_PRINTF2("%04x:", cs); + DECODE_PRINTF2("%04x\n", ip); + TRACE_AND_STEP(); + M.x86.R_EIP = ip & 0xffff; + M.x86.R_CS = cs; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xeb +****************************************************************************/ +static void +x86emuOp_jump_byte_IMM(u8 X86EMU_UNUSED(op1)) +{ + u16 target; + s8 offset; + + START_OF_INSTR(); + DECODE_PRINTF("JMP\t"); + offset = (s8) fetch_byte_imm(); + target = (u16) (M.x86.R_IP + offset); + DECODE_PRINTF2("%x\n", target); + TRACE_AND_STEP(); + M.x86.R_IP = target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xec +****************************************************************************/ +static void +x86emuOp_in_byte_AL_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("IN\tAL,DX\n"); + TRACE_AND_STEP(); + M.x86.R_AL = (*sys_inb) (M.x86.R_DX); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xed +****************************************************************************/ +static void +x86emuOp_in_word_AX_DX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("IN\tEAX,DX\n"); + } + else { + DECODE_PRINTF("IN\tAX,DX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_EAX = (*sys_inl) (M.x86.R_DX); + } + else { + M.x86.R_AX = (*sys_inw) (M.x86.R_DX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xee +****************************************************************************/ +static void +x86emuOp_out_byte_DX_AL(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("OUT\tDX,AL\n"); + TRACE_AND_STEP(); + (*sys_outb) (M.x86.R_DX, M.x86.R_AL); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xef +****************************************************************************/ +static void +x86emuOp_out_word_DX_AX(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("OUT\tDX,EAX\n"); + } + else { + DECODE_PRINTF("OUT\tDX,AX\n"); + } + TRACE_AND_STEP(); + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + (*sys_outl) (M.x86.R_DX, M.x86.R_EAX); + } + else { + (*sys_outw) (M.x86.R_DX, M.x86.R_AX); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf0 +****************************************************************************/ +static void +x86emuOp_lock(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("LOCK:\n"); + TRACE_AND_STEP(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/*opcode 0xf1 ILLEGAL OPERATION */ + +/**************************************************************************** +REMARKS: +Handles opcode 0xf2 +****************************************************************************/ +static void +x86emuOp_repne(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("REPNE\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_PREFIX_REPNE; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf3 +****************************************************************************/ +static void +x86emuOp_repe(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("REPE\n"); + TRACE_AND_STEP(); + M.x86.mode |= SYSMODE_PREFIX_REPE; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf4 +****************************************************************************/ +static void +x86emuOp_halt(u8 X86EMU_UNUSED(op1)) +{ + START_OF_INSTR(); + DECODE_PRINTF("HALT\n"); + TRACE_AND_STEP(); + HALT_SYS(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf5 +****************************************************************************/ +static void +x86emuOp_cmc(u8 X86EMU_UNUSED(op1)) +{ + /* complement the carry flag. */ + START_OF_INSTR(); + DECODE_PRINTF("CMC\n"); + TRACE_AND_STEP(); + TOGGLE_FLAG(F_CF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf6 +****************************************************************************/ +static void +x86emuOp_opcF6_byte_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + u8 *destreg; + uint destoffset; + u8 destval, srcval; + + /* long, drawn out code follows. Double switch for a total + of 32 cases. */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: /* mod=00 */ + switch (rh) { + case 0: /* test byte imm */ + DECODE_PRINTF("TEST\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%02x\n", srcval); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + test_byte(destval, srcval); + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + DECODE_PRINTF("NOT\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = not_byte(destval); + store_data_byte(destoffset, destval); + break; + case 3: + DECODE_PRINTF("NEG\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = neg_byte(destval); + store_data_byte(destoffset, destval); + break; + case 4: + DECODE_PRINTF("MUL\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + mul_byte(destval); + break; + case 5: + DECODE_PRINTF("IMUL\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + imul_byte(destval); + break; + case 6: + DECODE_PRINTF("DIV\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + div_byte(destval); + break; + case 7: + DECODE_PRINTF("IDIV\tBYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + idiv_byte(destval); + break; + } + break; /* end mod==00 */ + case 1: /* mod=01 */ + switch (rh) { + case 0: /* test byte imm */ + DECODE_PRINTF("TEST\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%02x\n", srcval); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + test_byte(destval, srcval); + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + DECODE_PRINTF("NOT\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = not_byte(destval); + store_data_byte(destoffset, destval); + break; + case 3: + DECODE_PRINTF("NEG\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = neg_byte(destval); + store_data_byte(destoffset, destval); + break; + case 4: + DECODE_PRINTF("MUL\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + mul_byte(destval); + break; + case 5: + DECODE_PRINTF("IMUL\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + imul_byte(destval); + break; + case 6: + DECODE_PRINTF("DIV\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + div_byte(destval); + break; + case 7: + DECODE_PRINTF("IDIV\tBYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + idiv_byte(destval); + break; + } + break; /* end mod==01 */ + case 2: /* mod=10 */ + switch (rh) { + case 0: /* test byte imm */ + DECODE_PRINTF("TEST\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%02x\n", srcval); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + test_byte(destval, srcval); + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + DECODE_PRINTF("NOT\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = not_byte(destval); + store_data_byte(destoffset, destval); + break; + case 3: + DECODE_PRINTF("NEG\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = neg_byte(destval); + store_data_byte(destoffset, destval); + break; + case 4: + DECODE_PRINTF("MUL\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + mul_byte(destval); + break; + case 5: + DECODE_PRINTF("IMUL\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + imul_byte(destval); + break; + case 6: + DECODE_PRINTF("DIV\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + div_byte(destval); + break; + case 7: + DECODE_PRINTF("IDIV\tBYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + idiv_byte(destval); + break; + } + break; /* end mod==10 */ + case 3: /* mod=11 */ + switch (rh) { + case 0: /* test byte imm */ + DECODE_PRINTF("TEST\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF(","); + srcval = fetch_byte_imm(); + DECODE_PRINTF2("%02x\n", srcval); + TRACE_AND_STEP(); + test_byte(*destreg, srcval); + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + DECODE_PRINTF("NOT\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = not_byte(*destreg); + break; + case 3: + DECODE_PRINTF("NEG\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = neg_byte(*destreg); + break; + case 4: + DECODE_PRINTF("MUL\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + mul_byte(*destreg); /*!!! */ + break; + case 5: + DECODE_PRINTF("IMUL\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + imul_byte(*destreg); + break; + case 6: + DECODE_PRINTF("DIV\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + div_byte(*destreg); + break; + case 7: + DECODE_PRINTF("IDIV\t"); + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + idiv_byte(*destreg); + break; + } + break; /* end mod==11 */ + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf7 +****************************************************************************/ +static void +x86emuOp_opcF7_word_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rl, rh; + uint destoffset; + + /* long, drawn out code follows. Double switch for a total + of 32 cases. */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: /* mod=00 */ + switch (rh) { + case 0: /* test word imm */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, srcval; + + DECODE_PRINTF("TEST\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcval = fetch_long_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + test_long(destval, srcval); + } + else { + u16 destval, srcval; + + DECODE_PRINTF("TEST\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + srcval = fetch_word_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + test_word(destval, srcval); + } + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F7\n"); + HALT_SYS(); + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NOT\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = not_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NOT\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = not_word(destval); + store_data_word(destoffset, destval); + } + break; + case 3: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NEG\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = neg_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NEG\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = neg_word(destval); + store_data_word(destoffset, destval); + } + break; + case 4: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("MUL\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + mul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("MUL\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + mul_word(destval); + } + break; + case 5: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IMUL\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + imul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IMUL\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + imul_word(destval); + } + break; + case 6: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DIV\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + div_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("DIV\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + div_word(destval); + } + break; + case 7: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IDIV\tDWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + idiv_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IDIV\tWORD PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + idiv_word(destval); + } + break; + } + break; /* end mod==00 */ + case 1: /* mod=01 */ + switch (rh) { + case 0: /* test word imm */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, srcval; + + DECODE_PRINTF("TEST\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcval = fetch_long_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + test_long(destval, srcval); + } + else { + u16 destval, srcval; + + DECODE_PRINTF("TEST\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + srcval = fetch_word_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + test_word(destval, srcval); + } + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=01 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NOT\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = not_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NOT\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = not_word(destval); + store_data_word(destoffset, destval); + } + break; + case 3: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NEG\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = neg_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NEG\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = neg_word(destval); + store_data_word(destoffset, destval); + } + break; + case 4: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("MUL\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + mul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("MUL\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + mul_word(destval); + } + break; + case 5: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IMUL\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + imul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IMUL\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + imul_word(destval); + } + break; + case 6: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DIV\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + div_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("DIV\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + div_word(destval); + } + break; + case 7: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IDIV\tDWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + idiv_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IDIV\tWORD PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + idiv_word(destval); + } + break; + } + break; /* end mod==01 */ + case 2: /* mod=10 */ + switch (rh) { + case 0: /* test word imm */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval, srcval; + + DECODE_PRINTF("TEST\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcval = fetch_long_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + test_long(destval, srcval); + } + else { + u16 destval, srcval; + + DECODE_PRINTF("TEST\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + srcval = fetch_word_imm(); + DECODE_PRINTF2("%x\n", srcval); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + test_word(destval, srcval); + } + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=10 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NOT\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = not_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NOT\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = not_word(destval); + store_data_word(destoffset, destval); + } + break; + case 3: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("NEG\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = neg_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + DECODE_PRINTF("NEG\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = neg_word(destval); + store_data_word(destoffset, destval); + } + break; + case 4: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("MUL\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + mul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("MUL\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + mul_word(destval); + } + break; + case 5: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IMUL\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + imul_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IMUL\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + imul_word(destval); + } + break; + case 6: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("DIV\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + div_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("DIV\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + div_word(destval); + } + break; + case 7: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + DECODE_PRINTF("IDIV\tDWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + idiv_long(destval); + } + else { + u16 destval; + + DECODE_PRINTF("IDIV\tWORD PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + idiv_word(destval); + } + break; + } + break; /* end mod==10 */ + case 3: /* mod=11 */ + switch (rh) { + case 0: /* test word imm */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + DECODE_PRINTF("TEST\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + srcval = fetch_long_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + test_long(*destreg, srcval); + } + else { + u16 *destreg; + u16 srcval; + + DECODE_PRINTF("TEST\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + srcval = fetch_word_imm(); + DECODE_PRINTF2("%x\n", srcval); + TRACE_AND_STEP(); + test_word(*destreg, srcval); + } + break; + case 1: + DECODE_PRINTF("ILLEGAL OP MOD=00 RH=01 OP=F6\n"); + HALT_SYS(); + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("NOT\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = not_long(*destreg); + } + else { + u16 *destreg; + + DECODE_PRINTF("NOT\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = not_word(*destreg); + } + break; + case 3: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("NEG\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = neg_long(*destreg); + } + else { + u16 *destreg; + + DECODE_PRINTF("NEG\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = neg_word(*destreg); + } + break; + case 4: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("MUL\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + mul_long(*destreg); /*!!! */ + } + else { + u16 *destreg; + + DECODE_PRINTF("MUL\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + mul_word(*destreg); /*!!! */ + } + break; + case 5: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("IMUL\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + imul_long(*destreg); + } + else { + u16 *destreg; + + DECODE_PRINTF("IMUL\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + imul_word(*destreg); + } + break; + case 6: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("DIV\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + div_long(*destreg); + } + else { + u16 *destreg; + + DECODE_PRINTF("DIV\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + div_word(*destreg); + } + break; + case 7: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + DECODE_PRINTF("IDIV\t"); + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + idiv_long(*destreg); + } + else { + u16 *destreg; + + DECODE_PRINTF("IDIV\t"); + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + idiv_word(*destreg); + } + break; + } + break; /* end mod==11 */ + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf8 +****************************************************************************/ +static void +x86emuOp_clc(u8 X86EMU_UNUSED(op1)) +{ + /* clear the carry flag. */ + START_OF_INSTR(); + DECODE_PRINTF("CLC\n"); + TRACE_AND_STEP(); + CLEAR_FLAG(F_CF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xf9 +****************************************************************************/ +static void +x86emuOp_stc(u8 X86EMU_UNUSED(op1)) +{ + /* set the carry flag. */ + START_OF_INSTR(); + DECODE_PRINTF("STC\n"); + TRACE_AND_STEP(); + SET_FLAG(F_CF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xfa +****************************************************************************/ +static void +x86emuOp_cli(u8 X86EMU_UNUSED(op1)) +{ + /* clear interrupts. */ + START_OF_INSTR(); + DECODE_PRINTF("CLI\n"); + TRACE_AND_STEP(); + CLEAR_FLAG(F_IF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xfb +****************************************************************************/ +static void +x86emuOp_sti(u8 X86EMU_UNUSED(op1)) +{ + /* enable interrupts. */ + START_OF_INSTR(); + DECODE_PRINTF("STI\n"); + TRACE_AND_STEP(); + SET_FLAG(F_IF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xfc +****************************************************************************/ +static void +x86emuOp_cld(u8 X86EMU_UNUSED(op1)) +{ + /* clear interrupts. */ + START_OF_INSTR(); + DECODE_PRINTF("CLD\n"); + TRACE_AND_STEP(); + CLEAR_FLAG(F_DF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xfd +****************************************************************************/ +static void +x86emuOp_std(u8 X86EMU_UNUSED(op1)) +{ + /* clear interrupts. */ + START_OF_INSTR(); + DECODE_PRINTF("STD\n"); + TRACE_AND_STEP(); + SET_FLAG(F_DF); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xfe +****************************************************************************/ +static void +x86emuOp_opcFE_byte_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rh, rl; + u8 destval; + uint destoffset; + u8 *destreg; + + /* Yet another special case instruction. */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + DECODE_PRINTF("INC\t"); + break; + case 1: + DECODE_PRINTF("DEC\t"); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + DECODE_PRINTF2("ILLEGAL OP MAJOR OP 0xFE MINOR OP %x \n", mod); + HALT_SYS(); + break; + } + } +#endif + switch (mod) { + case 0: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: /* inc word ptr ... */ + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = inc_byte(destval); + store_data_byte(destoffset, destval); + break; + case 1: /* dec word ptr ... */ + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = dec_byte(destval); + store_data_byte(destoffset, destval); + break; + } + break; + case 1: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = inc_byte(destval); + store_data_byte(destoffset, destval); + break; + case 1: + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = dec_byte(destval); + store_data_byte(destoffset, destval); + break; + } + break; + case 2: + DECODE_PRINTF("BYTE PTR "); + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = inc_byte(destval); + store_data_byte(destoffset, destval); + break; + case 1: + destval = fetch_data_byte(destoffset); + TRACE_AND_STEP(); + destval = dec_byte(destval); + store_data_byte(destoffset, destval); + break; + } + break; + case 3: + destreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: + TRACE_AND_STEP(); + *destreg = inc_byte(*destreg); + break; + case 1: + TRACE_AND_STEP(); + *destreg = dec_byte(*destreg); + break; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0xff +****************************************************************************/ +static void +x86emuOp_opcFF_word_RM(u8 X86EMU_UNUSED(op1)) +{ + int mod, rh, rl; + uint destoffset = 0; + u16 *destreg; + u16 destval, destval2; + + /* Yet another special case instruction. */ + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); +#ifdef DEBUG + if (DEBUG_DECODE()) { + /* XXX DECODE_PRINTF may be changed to something more + general, so that it is important to leave the strings + in the same format, even though the result is that the + above test is done twice. */ + + switch (rh) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("INC\tDWORD PTR "); + } + else { + DECODE_PRINTF("INC\tWORD PTR "); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + DECODE_PRINTF("DEC\tDWORD PTR "); + } + else { + DECODE_PRINTF("DEC\tWORD PTR "); + } + break; + case 2: + DECODE_PRINTF("CALL\t"); + break; + case 3: + DECODE_PRINTF("CALL\tFAR "); + break; + case 4: + DECODE_PRINTF("JMP\t"); + break; + case 5: + DECODE_PRINTF("JMP\tFAR "); + break; + case 6: + DECODE_PRINTF("PUSH\t"); + break; + case 7: + DECODE_PRINTF("ILLEGAL DECODING OF OPCODE FF\t"); + HALT_SYS(); + break; + } + } +#endif + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: /* inc word ptr ... */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = inc_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = inc_word(destval); + store_data_word(destoffset, destval); + } + break; + case 1: /* dec word ptr ... */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = dec_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = dec_word(destval); + store_data_word(destoffset, destval); + } + break; + case 2: /* call word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 3: /* call far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + push_word(M.x86.R_CS); + M.x86.R_CS = destval2; + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 4: /* jmp word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + break; + case 5: /* jmp far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + M.x86.R_CS = destval2; + break; + case 6: /* push word ptr ... */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + push_long(destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(destval); + } + break; + } + break; + case 1: + destoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = inc_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = inc_word(destval); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = dec_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = dec_word(destval); + store_data_word(destoffset, destval); + } + break; + case 2: /* call word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 3: /* call far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + push_word(M.x86.R_CS); + M.x86.R_CS = destval2; + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 4: /* jmp word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + break; + case 5: /* jmp far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + M.x86.R_CS = destval2; + break; + case 6: /* push word ptr ... */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + push_long(destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(destval); + } + break; + } + break; + case 2: + destoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + switch (rh) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = inc_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = inc_word(destval); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + destval = dec_long(destval); + store_data_long(destoffset, destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + destval = dec_word(destval); + store_data_word(destoffset, destval); + } + break; + case 2: /* call word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 3: /* call far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + push_word(M.x86.R_CS); + M.x86.R_CS = destval2; + push_word(M.x86.R_IP); + M.x86.R_IP = destval; + break; + case 4: /* jmp word ptr ... */ + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + break; + case 5: /* jmp far ptr ... */ + destval = fetch_data_word(destoffset); + destval2 = fetch_data_word(destoffset + 2); + TRACE_AND_STEP(); + M.x86.R_IP = destval; + M.x86.R_CS = destval2; + break; + case 6: /* push word ptr ... */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + + destval = fetch_data_long(destoffset); + TRACE_AND_STEP(); + push_long(destval); + } + else { + u16 destval; + + destval = fetch_data_word(destoffset); + TRACE_AND_STEP(); + push_word(destval); + } + break; + } + break; + case 3: + switch (rh) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = inc_long(*destreg); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = inc_word(*destreg); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = dec_long(*destreg); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = dec_word(*destreg); + } + break; + case 2: /* call word ptr ... */ + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_IP); + M.x86.R_IP = *destreg; + break; + case 3: /* jmp far ptr ... */ + DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); + TRACE_AND_STEP(); + HALT_SYS(); + break; + + case 4: /* jmp ... */ + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + M.x86.R_IP = (u16) (*destreg); + break; + case 5: /* jmp far ptr ... */ + DECODE_PRINTF("OPERATION UNDEFINED 0XFF \n"); + TRACE_AND_STEP(); + HALT_SYS(); + break; + case 6: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + push_long(*destreg); + } + else { + u16 *destreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + push_word(*destreg); + } + break; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/*************************************************************************** + * Single byte operation code table: + **************************************************************************/ +void (*x86emu_optab[256]) (u8) = { +/* 0x00 */ x86emuOp_add_byte_RM_R, +/* 0x01 */ x86emuOp_add_word_RM_R, +/* 0x02 */ x86emuOp_add_byte_R_RM, +/* 0x03 */ x86emuOp_add_word_R_RM, +/* 0x04 */ x86emuOp_add_byte_AL_IMM, +/* 0x05 */ x86emuOp_add_word_AX_IMM, +/* 0x06 */ x86emuOp_push_ES, +/* 0x07 */ x86emuOp_pop_ES, +/* 0x08 */ x86emuOp_or_byte_RM_R, +/* 0x09 */ x86emuOp_or_word_RM_R, +/* 0x0a */ x86emuOp_or_byte_R_RM, +/* 0x0b */ x86emuOp_or_word_R_RM, +/* 0x0c */ x86emuOp_or_byte_AL_IMM, +/* 0x0d */ x86emuOp_or_word_AX_IMM, +/* 0x0e */ x86emuOp_push_CS, +/* 0x0f */ x86emuOp_two_byte, +/* 0x10 */ x86emuOp_adc_byte_RM_R, +/* 0x11 */ x86emuOp_adc_word_RM_R, +/* 0x12 */ x86emuOp_adc_byte_R_RM, +/* 0x13 */ x86emuOp_adc_word_R_RM, +/* 0x14 */ x86emuOp_adc_byte_AL_IMM, +/* 0x15 */ x86emuOp_adc_word_AX_IMM, +/* 0x16 */ x86emuOp_push_SS, +/* 0x17 */ x86emuOp_pop_SS, +/* 0x18 */ x86emuOp_sbb_byte_RM_R, +/* 0x19 */ x86emuOp_sbb_word_RM_R, +/* 0x1a */ x86emuOp_sbb_byte_R_RM, +/* 0x1b */ x86emuOp_sbb_word_R_RM, +/* 0x1c */ x86emuOp_sbb_byte_AL_IMM, +/* 0x1d */ x86emuOp_sbb_word_AX_IMM, +/* 0x1e */ x86emuOp_push_DS, +/* 0x1f */ x86emuOp_pop_DS, +/* 0x20 */ x86emuOp_and_byte_RM_R, +/* 0x21 */ x86emuOp_and_word_RM_R, +/* 0x22 */ x86emuOp_and_byte_R_RM, +/* 0x23 */ x86emuOp_and_word_R_RM, +/* 0x24 */ x86emuOp_and_byte_AL_IMM, +/* 0x25 */ x86emuOp_and_word_AX_IMM, +/* 0x26 */ x86emuOp_segovr_ES, +/* 0x27 */ x86emuOp_daa, +/* 0x28 */ x86emuOp_sub_byte_RM_R, +/* 0x29 */ x86emuOp_sub_word_RM_R, +/* 0x2a */ x86emuOp_sub_byte_R_RM, +/* 0x2b */ x86emuOp_sub_word_R_RM, +/* 0x2c */ x86emuOp_sub_byte_AL_IMM, +/* 0x2d */ x86emuOp_sub_word_AX_IMM, +/* 0x2e */ x86emuOp_segovr_CS, +/* 0x2f */ x86emuOp_das, +/* 0x30 */ x86emuOp_xor_byte_RM_R, +/* 0x31 */ x86emuOp_xor_word_RM_R, +/* 0x32 */ x86emuOp_xor_byte_R_RM, +/* 0x33 */ x86emuOp_xor_word_R_RM, +/* 0x34 */ x86emuOp_xor_byte_AL_IMM, +/* 0x35 */ x86emuOp_xor_word_AX_IMM, +/* 0x36 */ x86emuOp_segovr_SS, +/* 0x37 */ x86emuOp_aaa, +/* 0x38 */ x86emuOp_cmp_byte_RM_R, +/* 0x39 */ x86emuOp_cmp_word_RM_R, +/* 0x3a */ x86emuOp_cmp_byte_R_RM, +/* 0x3b */ x86emuOp_cmp_word_R_RM, +/* 0x3c */ x86emuOp_cmp_byte_AL_IMM, +/* 0x3d */ x86emuOp_cmp_word_AX_IMM, +/* 0x3e */ x86emuOp_segovr_DS, +/* 0x3f */ x86emuOp_aas, +/* 0x40 */ x86emuOp_inc_AX, +/* 0x41 */ x86emuOp_inc_CX, +/* 0x42 */ x86emuOp_inc_DX, +/* 0x43 */ x86emuOp_inc_BX, +/* 0x44 */ x86emuOp_inc_SP, +/* 0x45 */ x86emuOp_inc_BP, +/* 0x46 */ x86emuOp_inc_SI, +/* 0x47 */ x86emuOp_inc_DI, +/* 0x48 */ x86emuOp_dec_AX, +/* 0x49 */ x86emuOp_dec_CX, +/* 0x4a */ x86emuOp_dec_DX, +/* 0x4b */ x86emuOp_dec_BX, +/* 0x4c */ x86emuOp_dec_SP, +/* 0x4d */ x86emuOp_dec_BP, +/* 0x4e */ x86emuOp_dec_SI, +/* 0x4f */ x86emuOp_dec_DI, +/* 0x50 */ x86emuOp_push_AX, +/* 0x51 */ x86emuOp_push_CX, +/* 0x52 */ x86emuOp_push_DX, +/* 0x53 */ x86emuOp_push_BX, +/* 0x54 */ x86emuOp_push_SP, +/* 0x55 */ x86emuOp_push_BP, +/* 0x56 */ x86emuOp_push_SI, +/* 0x57 */ x86emuOp_push_DI, +/* 0x58 */ x86emuOp_pop_AX, +/* 0x59 */ x86emuOp_pop_CX, +/* 0x5a */ x86emuOp_pop_DX, +/* 0x5b */ x86emuOp_pop_BX, +/* 0x5c */ x86emuOp_pop_SP, +/* 0x5d */ x86emuOp_pop_BP, +/* 0x5e */ x86emuOp_pop_SI, +/* 0x5f */ x86emuOp_pop_DI, +/* 0x60 */ x86emuOp_push_all, +/* 0x61 */ x86emuOp_pop_all, + /* 0x62 */ x86emuOp_illegal_op, + /* bound */ + /* 0x63 */ x86emuOp_illegal_op, + /* arpl */ +/* 0x64 */ x86emuOp_segovr_FS, +/* 0x65 */ x86emuOp_segovr_GS, +/* 0x66 */ x86emuOp_prefix_data, +/* 0x67 */ x86emuOp_prefix_addr, +/* 0x68 */ x86emuOp_push_word_IMM, +/* 0x69 */ x86emuOp_imul_word_IMM, +/* 0x6a */ x86emuOp_push_byte_IMM, +/* 0x6b */ x86emuOp_imul_byte_IMM, +/* 0x6c */ x86emuOp_ins_byte, +/* 0x6d */ x86emuOp_ins_word, +/* 0x6e */ x86emuOp_outs_byte, +/* 0x6f */ x86emuOp_outs_word, +/* 0x70 */ x86emuOp_jump_near_O, +/* 0x71 */ x86emuOp_jump_near_NO, +/* 0x72 */ x86emuOp_jump_near_B, +/* 0x73 */ x86emuOp_jump_near_NB, +/* 0x74 */ x86emuOp_jump_near_Z, +/* 0x75 */ x86emuOp_jump_near_NZ, +/* 0x76 */ x86emuOp_jump_near_BE, +/* 0x77 */ x86emuOp_jump_near_NBE, +/* 0x78 */ x86emuOp_jump_near_S, +/* 0x79 */ x86emuOp_jump_near_NS, +/* 0x7a */ x86emuOp_jump_near_P, +/* 0x7b */ x86emuOp_jump_near_NP, +/* 0x7c */ x86emuOp_jump_near_L, +/* 0x7d */ x86emuOp_jump_near_NL, +/* 0x7e */ x86emuOp_jump_near_LE, +/* 0x7f */ x86emuOp_jump_near_NLE, +/* 0x80 */ x86emuOp_opc80_byte_RM_IMM, +/* 0x81 */ x86emuOp_opc81_word_RM_IMM, +/* 0x82 */ x86emuOp_opc82_byte_RM_IMM, +/* 0x83 */ x86emuOp_opc83_word_RM_IMM, +/* 0x84 */ x86emuOp_test_byte_RM_R, +/* 0x85 */ x86emuOp_test_word_RM_R, +/* 0x86 */ x86emuOp_xchg_byte_RM_R, +/* 0x87 */ x86emuOp_xchg_word_RM_R, +/* 0x88 */ x86emuOp_mov_byte_RM_R, +/* 0x89 */ x86emuOp_mov_word_RM_R, +/* 0x8a */ x86emuOp_mov_byte_R_RM, +/* 0x8b */ x86emuOp_mov_word_R_RM, +/* 0x8c */ x86emuOp_mov_word_RM_SR, +/* 0x8d */ x86emuOp_lea_word_R_M, +/* 0x8e */ x86emuOp_mov_word_SR_RM, +/* 0x8f */ x86emuOp_pop_RM, +/* 0x90 */ x86emuOp_nop, +/* 0x91 */ x86emuOp_xchg_word_AX_CX, +/* 0x92 */ x86emuOp_xchg_word_AX_DX, +/* 0x93 */ x86emuOp_xchg_word_AX_BX, +/* 0x94 */ x86emuOp_xchg_word_AX_SP, +/* 0x95 */ x86emuOp_xchg_word_AX_BP, +/* 0x96 */ x86emuOp_xchg_word_AX_SI, +/* 0x97 */ x86emuOp_xchg_word_AX_DI, +/* 0x98 */ x86emuOp_cbw, +/* 0x99 */ x86emuOp_cwd, +/* 0x9a */ x86emuOp_call_far_IMM, +/* 0x9b */ x86emuOp_wait, +/* 0x9c */ x86emuOp_pushf_word, +/* 0x9d */ x86emuOp_popf_word, +/* 0x9e */ x86emuOp_sahf, +/* 0x9f */ x86emuOp_lahf, +/* 0xa0 */ x86emuOp_mov_AL_M_IMM, +/* 0xa1 */ x86emuOp_mov_AX_M_IMM, +/* 0xa2 */ x86emuOp_mov_M_AL_IMM, +/* 0xa3 */ x86emuOp_mov_M_AX_IMM, +/* 0xa4 */ x86emuOp_movs_byte, +/* 0xa5 */ x86emuOp_movs_word, +/* 0xa6 */ x86emuOp_cmps_byte, +/* 0xa7 */ x86emuOp_cmps_word, +/* 0xa8 */ x86emuOp_test_AL_IMM, +/* 0xa9 */ x86emuOp_test_AX_IMM, +/* 0xaa */ x86emuOp_stos_byte, +/* 0xab */ x86emuOp_stos_word, +/* 0xac */ x86emuOp_lods_byte, +/* 0xad */ x86emuOp_lods_word, +/* 0xac */ x86emuOp_scas_byte, +/* 0xad */ x86emuOp_scas_word, +/* 0xb0 */ x86emuOp_mov_byte_AL_IMM, +/* 0xb1 */ x86emuOp_mov_byte_CL_IMM, +/* 0xb2 */ x86emuOp_mov_byte_DL_IMM, +/* 0xb3 */ x86emuOp_mov_byte_BL_IMM, +/* 0xb4 */ x86emuOp_mov_byte_AH_IMM, +/* 0xb5 */ x86emuOp_mov_byte_CH_IMM, +/* 0xb6 */ x86emuOp_mov_byte_DH_IMM, +/* 0xb7 */ x86emuOp_mov_byte_BH_IMM, +/* 0xb8 */ x86emuOp_mov_word_AX_IMM, +/* 0xb9 */ x86emuOp_mov_word_CX_IMM, +/* 0xba */ x86emuOp_mov_word_DX_IMM, +/* 0xbb */ x86emuOp_mov_word_BX_IMM, +/* 0xbc */ x86emuOp_mov_word_SP_IMM, +/* 0xbd */ x86emuOp_mov_word_BP_IMM, +/* 0xbe */ x86emuOp_mov_word_SI_IMM, +/* 0xbf */ x86emuOp_mov_word_DI_IMM, +/* 0xc0 */ x86emuOp_opcC0_byte_RM_MEM, +/* 0xc1 */ x86emuOp_opcC1_word_RM_MEM, +/* 0xc2 */ x86emuOp_ret_near_IMM, +/* 0xc3 */ x86emuOp_ret_near, +/* 0xc4 */ x86emuOp_les_R_IMM, +/* 0xc5 */ x86emuOp_lds_R_IMM, +/* 0xc6 */ x86emuOp_mov_byte_RM_IMM, +/* 0xc7 */ x86emuOp_mov_word_RM_IMM, +/* 0xc8 */ x86emuOp_enter, +/* 0xc9 */ x86emuOp_leave, +/* 0xca */ x86emuOp_ret_far_IMM, +/* 0xcb */ x86emuOp_ret_far, +/* 0xcc */ x86emuOp_int3, +/* 0xcd */ x86emuOp_int_IMM, +/* 0xce */ x86emuOp_into, +/* 0xcf */ x86emuOp_iret, +/* 0xd0 */ x86emuOp_opcD0_byte_RM_1, +/* 0xd1 */ x86emuOp_opcD1_word_RM_1, +/* 0xd2 */ x86emuOp_opcD2_byte_RM_CL, +/* 0xd3 */ x86emuOp_opcD3_word_RM_CL, +/* 0xd4 */ x86emuOp_aam, +/* 0xd5 */ x86emuOp_aad, + /* 0xd6 */ x86emuOp_illegal_op, + /* Undocumented SETALC instruction */ +/* 0xd7 */ x86emuOp_xlat, +/* 0xd8 */ x86emuOp_esc_coprocess_d8, +/* 0xd9 */ x86emuOp_esc_coprocess_d9, +/* 0xda */ x86emuOp_esc_coprocess_da, +/* 0xdb */ x86emuOp_esc_coprocess_db, +/* 0xdc */ x86emuOp_esc_coprocess_dc, +/* 0xdd */ x86emuOp_esc_coprocess_dd, +/* 0xde */ x86emuOp_esc_coprocess_de, +/* 0xdf */ x86emuOp_esc_coprocess_df, +/* 0xe0 */ x86emuOp_loopne, +/* 0xe1 */ x86emuOp_loope, +/* 0xe2 */ x86emuOp_loop, +/* 0xe3 */ x86emuOp_jcxz, +/* 0xe4 */ x86emuOp_in_byte_AL_IMM, +/* 0xe5 */ x86emuOp_in_word_AX_IMM, +/* 0xe6 */ x86emuOp_out_byte_IMM_AL, +/* 0xe7 */ x86emuOp_out_word_IMM_AX, +/* 0xe8 */ x86emuOp_call_near_IMM, +/* 0xe9 */ x86emuOp_jump_near_IMM, +/* 0xea */ x86emuOp_jump_far_IMM, +/* 0xeb */ x86emuOp_jump_byte_IMM, +/* 0xec */ x86emuOp_in_byte_AL_DX, +/* 0xed */ x86emuOp_in_word_AX_DX, +/* 0xee */ x86emuOp_out_byte_DX_AL, +/* 0xef */ x86emuOp_out_word_DX_AX, +/* 0xf0 */ x86emuOp_lock, +/* 0xf1 */ x86emuOp_illegal_op, +/* 0xf2 */ x86emuOp_repne, +/* 0xf3 */ x86emuOp_repe, +/* 0xf4 */ x86emuOp_halt, +/* 0xf5 */ x86emuOp_cmc, +/* 0xf6 */ x86emuOp_opcF6_byte_RM, +/* 0xf7 */ x86emuOp_opcF7_word_RM, +/* 0xf8 */ x86emuOp_clc, +/* 0xf9 */ x86emuOp_stc, +/* 0xfa */ x86emuOp_cli, +/* 0xfb */ x86emuOp_sti, +/* 0xfc */ x86emuOp_cld, +/* 0xfd */ x86emuOp_std, +/* 0xfe */ x86emuOp_opcFE_byte_RM, +/* 0xff */ x86emuOp_opcFF_word_RM, +}; diff --git a/src/add-ons/kernel/generic/bios/x86emu/ops2.c b/src/add-ons/kernel/generic/bios/x86emu/ops2.c new file mode 100644 index 0000000000..5ed2bf68d3 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/ops2.c @@ -0,0 +1,3008 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file includes subroutines to implement the decoding +* and emulation of all the x86 extended two-byte processor +* instructions. +* +****************************************************************************/ + +#include "x86emu/x86emui.h" + +#undef bswap_32 +#define bswap_32(x) (((x & 0xff000000) >> 24) | \ + ((x & 0x00ff0000) >> 8) | \ + ((x & 0x0000ff00) << 8) | \ + ((x & 0x000000ff) << 24)) + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +PARAMETERS: +op1 - Instruction op code + +REMARKS: +Handles illegal opcodes. +****************************************************************************/ +static void +x86emuOp2_illegal_op(u8 op2) +{ + START_OF_INSTR(); + DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); + TRACE_REGS(); + printk("%04x:%04x: %02X ILLEGAL EXTENDED X86 OPCODE!\n", + M.x86.R_CS, M.x86.R_IP - 2, op2); + HALT_SYS(); + END_OF_INSTR(); +} + +#define xorl(a,b) ((a) && !(b)) || (!(a) && (b)) + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x31 +****************************************************************************/ +static void +x86emuOp2_rdtsc(u8 X86EMU_UNUSED(op2)) +{ +#ifdef __HAS_LONG_LONG__ + static u64 counter = 0; +#else + static u32 counter = 0; +#endif + + counter += 0x10000; + + /* read timestamp counter */ + /* + * Note that instead of actually trying to accurately measure this, we just + * increase the counter by a fixed amount every time we hit one of these + * instructions. Feel free to come up with a better method. + */ + START_OF_INSTR(); + DECODE_PRINTF("RDTSC\n"); + TRACE_AND_STEP(); +#ifdef __HAS_LONG_LONG__ + M.x86.R_EAX = counter & 0xffffffff; + M.x86.R_EDX = counter >> 32; +#else + M.x86.R_EAX = counter; + M.x86.R_EDX = 0; +#endif + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x80-0x8F +****************************************************************************/ +static void +x86emuOp2_long_jump(u8 op2) +{ + s32 target; + const char *name = NULL; + int cond = 0; + + /* conditional jump to word offset. */ + START_OF_INSTR(); + switch (op2) { + case 0x80: + name = "JO\t"; + cond = ACCESS_FLAG(F_OF); + break; + case 0x81: + name = "JNO\t"; + cond = !ACCESS_FLAG(F_OF); + break; + case 0x82: + name = "JB\t"; + cond = ACCESS_FLAG(F_CF); + break; + case 0x83: + name = "JNB\t"; + cond = !ACCESS_FLAG(F_CF); + break; + case 0x84: + name = "JZ\t"; + cond = ACCESS_FLAG(F_ZF); + break; + case 0x85: + name = "JNZ\t"; + cond = !ACCESS_FLAG(F_ZF); + break; + case 0x86: + name = "JBE\t"; + cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); + break; + case 0x87: + name = "JNBE\t"; + cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); + break; + case 0x88: + name = "JS\t"; + cond = ACCESS_FLAG(F_SF); + break; + case 0x89: + name = "JNS\t"; + cond = !ACCESS_FLAG(F_SF); + break; + case 0x8a: + name = "JP\t"; + cond = ACCESS_FLAG(F_PF); + break; + case 0x8b: + name = "JNP\t"; + cond = !ACCESS_FLAG(F_PF); + break; + case 0x8c: + name = "JL\t"; + cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); + break; + case 0x8d: + name = "JNL\t"; + cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))); + break; + case 0x8e: + name = "JLE\t"; + cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || + ACCESS_FLAG(F_ZF)); + break; + case 0x8f: + name = "JNLE\t"; + cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || + ACCESS_FLAG(F_ZF)); + break; + } + DECODE_PRINTF(name); + (void) name; + target = (s16) fetch_word_imm(); + target += (s16) M.x86.R_IP; + DECODE_PRINTF2("%04x\n", target); + TRACE_AND_STEP(); + if (cond) + M.x86.R_IP = (u16) target; + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0x90-0x9F +****************************************************************************/ +static void +x86emuOp2_set_byte(u8 op2) +{ + int mod, rl, rh; + uint destoffset; + u8 *destreg; + const char *name = NULL; + int cond = 0; + + START_OF_INSTR(); + switch (op2) { + case 0x90: + name = "SETO\t"; + cond = ACCESS_FLAG(F_OF); + break; + case 0x91: + name = "SETNO\t"; + cond = !ACCESS_FLAG(F_OF); + break; + case 0x92: + name = "SETB\t"; + cond = ACCESS_FLAG(F_CF); + break; + case 0x93: + name = "SETNB\t"; + cond = !ACCESS_FLAG(F_CF); + break; + case 0x94: + name = "SETZ\t"; + cond = ACCESS_FLAG(F_ZF); + break; + case 0x95: + name = "SETNZ\t"; + cond = !ACCESS_FLAG(F_ZF); + break; + case 0x96: + name = "SETBE\t"; + cond = ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF); + break; + case 0x97: + name = "SETNBE\t"; + cond = !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)); + break; + case 0x98: + name = "SETS\t"; + cond = ACCESS_FLAG(F_SF); + break; + case 0x99: + name = "SETNS\t"; + cond = !ACCESS_FLAG(F_SF); + break; + case 0x9a: + name = "SETP\t"; + cond = ACCESS_FLAG(F_PF); + break; + case 0x9b: + name = "SETNP\t"; + cond = !ACCESS_FLAG(F_PF); + break; + case 0x9c: + name = "SETL\t"; + cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); + break; + case 0x9d: + name = "SETNL\t"; + cond = xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)); + break; + case 0x9e: + name = "SETLE\t"; + cond = (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || + ACCESS_FLAG(F_ZF)); + break; + case 0x9f: + name = "SETNLE\t"; + cond = !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) || + ACCESS_FLAG(F_ZF)); + break; + } + DECODE_PRINTF(name); + (void) name; + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destoffset = decode_rm00_address(rl); + TRACE_AND_STEP(); + store_data_byte(destoffset, cond ? 0x01 : 0x00); + break; + case 1: + destoffset = decode_rm01_address(rl); + TRACE_AND_STEP(); + store_data_byte(destoffset, cond ? 0x01 : 0x00); + break; + case 2: + destoffset = decode_rm10_address(rl); + TRACE_AND_STEP(); + store_data_byte(destoffset, cond ? 0x01 : 0x00); + break; + case 3: /* register to register */ + destreg = DECODE_RM_BYTE_REGISTER(rl); + TRACE_AND_STEP(); + *destreg = cond ? 0x01 : 0x00; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa0 +****************************************************************************/ +static void +x86emuOp2_push_FS(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tFS\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_FS); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa1 +****************************************************************************/ +static void +x86emuOp2_pop_FS(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("POP\tFS\n"); + TRACE_AND_STEP(); + M.x86.R_FS = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output +Handles opcode 0x0f,0xa2 +****************************************************************************/ +static void +x86emuOp2_cpuid(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("CPUID\n"); + TRACE_AND_STEP(); + cpuid(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa3 +****************************************************************************/ +static void +x86emuOp2_bt_R(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + int bit, disp; + + START_OF_INSTR(); + DECODE_PRINTF("BT\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval; + u32 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + else { + u16 srcval; + u16 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval; + u32 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + else { + u16 srcval; + u16 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval; + u32 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + else { + u16 srcval; + u16 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + CONDITIONAL_SET_FLAG(srcval & (0x1 << bit), F_CF); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg, *shiftreg; + + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit), F_CF); + } + else { + u16 *srcreg, *shiftreg; + + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + CONDITIONAL_SET_FLAG(*srcreg & (0x1 << bit), F_CF); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa4 +****************************************************************************/ +static void +x86emuOp2_shld_IMM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint destoffset; + u8 shift; + + START_OF_INSTR(); + DECODE_PRINTF("SHLD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *shiftreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + *destreg = shld_long(*destreg, *shiftreg, shift); + } + else { + u16 *destreg, *shiftreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + *destreg = shld_word(*destreg, *shiftreg, shift); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa5 +****************************************************************************/ +static void +x86emuOp2_shld_CL(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SHLD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shld_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shld_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *shiftreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = shld_long(*destreg, *shiftreg, M.x86.R_CL); + } + else { + u16 *destreg, *shiftreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = shld_word(*destreg, *shiftreg, M.x86.R_CL); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa8 +****************************************************************************/ +static void +x86emuOp2_push_GS(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("PUSH\tGS\n"); + TRACE_AND_STEP(); + push_word(M.x86.R_GS); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xa9 +****************************************************************************/ +static void +x86emuOp2_pop_GS(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("POP\tGS\n"); + TRACE_AND_STEP(); + M.x86.R_GS = pop_word(); + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xab +****************************************************************************/ +static void +x86emuOp2_bts_R(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + int bit, disp; + + START_OF_INSTR(); + DECODE_PRINTF("BTS\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval | mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, srcval | mask); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval | mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, srcval | mask); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval | mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, srcval | mask); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg, *shiftreg; + u32 mask; + + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg |= mask; + } + else { + u16 *srcreg, *shiftreg; + u16 mask; + + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg |= mask; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xac +****************************************************************************/ +static void +x86emuOp2_shrd_IMM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint destoffset; + u8 shift; + + START_OF_INSTR(); + DECODE_PRINTF("SHLD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, shift); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, shift); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *shiftreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + *destreg = shrd_long(*destreg, *shiftreg, shift); + } + else { + u16 *destreg, *shiftreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + DECODE_PRINTF2("%d\n", shift); + TRACE_AND_STEP(); + *destreg = shrd_word(*destreg, *shiftreg, shift); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xad +****************************************************************************/ +static void +x86emuOp2_shrd_CL(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint destoffset; + + START_OF_INSTR(); + DECODE_PRINTF("SHLD\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 destval; + u32 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_long(destoffset); + destval = shrd_long(destval, *shiftreg, M.x86.R_CL); + store_data_long(destoffset, destval); + } + else { + u16 destval; + u16 *shiftreg; + + destoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + destval = fetch_data_word(destoffset); + destval = shrd_word(destval, *shiftreg, M.x86.R_CL); + store_data_word(destoffset, destval); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *shiftreg; + + destreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = shrd_long(*destreg, *shiftreg, M.x86.R_CL); + } + else { + u16 *destreg, *shiftreg; + + destreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(",CL\n"); + TRACE_AND_STEP(); + *destreg = shrd_word(*destreg, *shiftreg, M.x86.R_CL); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xaf +****************************************************************************/ +static void +x86emuOp2_imul_R_RM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("IMUL\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_long(srcoffset); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * destreg, (s32) srcval); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + TRACE_AND_STEP(); + res = (s16) * destreg * (s16) srcval; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_long(srcoffset); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * destreg, (s32) srcval); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + TRACE_AND_STEP(); + res = (s16) * destreg * (s16) srcval; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_long(srcoffset); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * destreg, (s32) srcval); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg; + u16 srcval; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + TRACE_AND_STEP(); + res = (s16) * destreg * (s16) srcval; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg, *srcreg; + u32 res_lo, res_hi; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_LONG_REGISTER(rl); + TRACE_AND_STEP(); + imul_long_direct(&res_lo, &res_hi, (s32) * destreg, (s32) * srcreg); + if (res_hi != 0) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u32) res_lo; + } + else { + u16 *destreg, *srcreg; + u32 res; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + res = (s16) * destreg * (s16) * srcreg; + if (res > 0xFFFF) { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + *destreg = (u16) res; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb2 +****************************************************************************/ +static void +x86emuOp2_lss_R_IMM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rh, rl; + u16 *dstreg; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LSS\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_SS = fetch_data_word(srcoffset + 2); + break; + case 1: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_SS = fetch_data_word(srcoffset + 2); + break; + case 2: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_SS = fetch_data_word(srcoffset + 2); + break; + case 3: /* register to register */ + /* UNDEFINED! */ + TRACE_AND_STEP(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb3 +****************************************************************************/ +static void +x86emuOp2_btr_R(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + int bit, disp; + + START_OF_INSTR(); + DECODE_PRINTF("BTR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval & ~mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval & ~mask)); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval & ~mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval & ~mask)); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval & ~mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval & ~mask)); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg, *shiftreg; + u32 mask; + + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg &= ~mask; + } + else { + u16 *srcreg, *shiftreg; + u16 mask; + + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg &= ~mask; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb4 +****************************************************************************/ +static void +x86emuOp2_lfs_R_IMM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rh, rl; + u16 *dstreg; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LFS\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_FS = fetch_data_word(srcoffset + 2); + break; + case 1: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_FS = fetch_data_word(srcoffset + 2); + break; + case 2: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_FS = fetch_data_word(srcoffset + 2); + break; + case 3: /* register to register */ + /* UNDEFINED! */ + TRACE_AND_STEP(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb5 +****************************************************************************/ +static void +x86emuOp2_lgs_R_IMM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rh, rl; + u16 *dstreg; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("LGS\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_GS = fetch_data_word(srcoffset + 2); + break; + case 1: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_GS = fetch_data_word(srcoffset + 2); + break; + case 2: + dstreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *dstreg = fetch_data_word(srcoffset); + M.x86.R_GS = fetch_data_word(srcoffset + 2); + break; + case 3: /* register to register */ + /* UNDEFINED! */ + TRACE_AND_STEP(); + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb6 +****************************************************************************/ +static void +x86emuOp2_movzx_byte_R_RM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOVZX\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_byte(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u8 *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + else { + u16 *destreg; + u8 *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xb7 +****************************************************************************/ +static void +x86emuOp2_movzx_word_R_RM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + u32 *destreg; + u32 srcval; + u16 *srcreg; + + START_OF_INSTR(); + DECODE_PRINTF("MOVZX\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 1: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 2: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = fetch_data_word(srcoffset); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 3: /* register to register */ + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = *srcreg; + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xba +****************************************************************************/ +static void +x86emuOp2_btX_I(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + int bit; + + START_OF_INSTR(); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (rh) { + case 4: + DECODE_PRINTF("BT\t"); + break; + case 5: + DECODE_PRINTF("BTS\t"); + break; + case 6: + DECODE_PRINTF("BTR\t"); + break; + case 7: + DECODE_PRINTF("BTC\t"); + break; + default: + DECODE_PRINTF("ILLEGAL EXTENDED X86 OPCODE\n"); + TRACE_REGS(); + printk("%04x:%04x: %02X%02X ILLEGAL EXTENDED X86 OPCODE EXTENSION!\n", + M.x86.R_CS, M.x86.R_IP - 3, op2, (mod << 6) | (rh << 3) | rl); + HALT_SYS(); + } + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u8 shift; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0x1F; + srcval = fetch_data_long(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_long(srcoffset, srcval | mask); + break; + case 6: + store_data_long(srcoffset, srcval & ~mask); + break; + case 7: + store_data_long(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + else { + u16 srcval, mask; + u8 shift; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0xF; + srcval = fetch_data_word(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_word(srcoffset, srcval | mask); + break; + case 6: + store_data_word(srcoffset, srcval & ~mask); + break; + case 7: + store_data_word(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u8 shift; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0x1F; + srcval = fetch_data_long(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_long(srcoffset, srcval | mask); + break; + case 6: + store_data_long(srcoffset, srcval & ~mask); + break; + case 7: + store_data_long(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + else { + u16 srcval, mask; + u8 shift; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0xF; + srcval = fetch_data_word(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_word(srcoffset, srcval | mask); + break; + case 6: + store_data_word(srcoffset, srcval & ~mask); + break; + case 7: + store_data_word(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u8 shift; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0x1F; + srcval = fetch_data_long(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_long(srcoffset, srcval | mask); + break; + case 6: + store_data_long(srcoffset, srcval & ~mask); + break; + case 7: + store_data_long(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + else { + u16 srcval, mask; + u8 shift; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0xF; + srcval = fetch_data_word(srcoffset); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + switch (rh) { + case 5: + store_data_word(srcoffset, srcval | mask); + break; + case 6: + store_data_word(srcoffset, srcval & ~mask); + break; + case 7: + store_data_word(srcoffset, srcval ^ mask); + break; + default: + break; + } + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg; + u32 mask; + u8 shift; + + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0x1F; + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + switch (rh) { + case 5: + *srcreg |= mask; + break; + case 6: + *srcreg &= ~mask; + break; + case 7: + *srcreg ^= mask; + break; + default: + break; + } + } + else { + u16 *srcreg; + u16 mask; + u8 shift; + + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shift = fetch_byte_imm(); + TRACE_AND_STEP(); + bit = shift & 0xF; + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + switch (rh) { + case 5: + *srcreg |= mask; + break; + case 6: + *srcreg &= ~mask; + break; + case 7: + *srcreg ^= mask; + break; + default: + break; + } + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xbb +****************************************************************************/ +static void +x86emuOp2_btc_R(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + int bit, disp; + + START_OF_INSTR(); + DECODE_PRINTF("BTC\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval ^ mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval ^ mask)); + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval ^ mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval ^ mask)); + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, mask; + u32 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + disp = (s16) * shiftreg >> 5; + srcval = fetch_data_long(srcoffset + disp); + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_long(srcoffset + disp, srcval ^ mask); + } + else { + u16 srcval, mask; + u16 *shiftreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + disp = (s16) * shiftreg >> 4; + srcval = fetch_data_word(srcoffset + disp); + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(srcval & mask, F_CF); + store_data_word(srcoffset + disp, (u16) (srcval ^ mask)); + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *srcreg, *shiftreg; + u32 mask; + + srcreg = DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0x1F; + mask = (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg ^= mask; + } + else { + u16 *srcreg, *shiftreg; + u16 mask; + + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + shiftreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + bit = *shiftreg & 0xF; + mask = (u16) (0x1 << bit); + CONDITIONAL_SET_FLAG(*srcreg & mask, F_CF); + *srcreg ^= mask; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xbc +****************************************************************************/ +static void +x86emuOp2_bsf(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("BSF\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 32; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 16; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 32; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 16; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 32; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 16; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcval = *DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 32; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcval = *DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 0; *dstreg < 16; (*dstreg)++) + if ((srcval >> *dstreg) & 1) + break; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xbd +****************************************************************************/ +static void +x86emuOp2_bsr(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("BSR\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 31; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm00_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 15; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 31; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm01_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 15; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_long(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 31; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcoffset = decode_rm10_address(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + srcval = fetch_data_word(srcoffset); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 15; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 srcval, *dstreg; + + srcval = *DECODE_RM_LONG_REGISTER(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_LONG_REGISTER(rh); + TRACE_AND_STEP(); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 31; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + else { + u16 srcval, *dstreg; + + srcval = *DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF(","); + dstreg = DECODE_RM_WORD_REGISTER(rh); + TRACE_AND_STEP(); + CONDITIONAL_SET_FLAG(srcval == 0, F_ZF); + for (*dstreg = 15; *dstreg > 0; (*dstreg)--) + if ((srcval >> *dstreg) & 1) + break; + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xbe +****************************************************************************/ +static void +x86emuOp2_movsx_byte_R_RM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + + START_OF_INSTR(); + DECODE_PRINTF("MOVSX\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = (s32) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = (s16) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 1: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = (s32) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = (s16) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 2: + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u32 srcval; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = (s32) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + else { + u16 *destreg; + u16 srcval; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = (s16) ((s8) fetch_data_byte(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + } + break; + case 3: /* register to register */ + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + u32 *destreg; + u8 *srcreg; + + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = (s32) ((s8) * srcreg); + } + else { + u16 *destreg; + u8 *srcreg; + + destreg = DECODE_RM_WORD_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_BYTE_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = (s16) ((s8) * srcreg); + } + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/**************************************************************************** +REMARKS: +Handles opcode 0x0f,0xbf +****************************************************************************/ +static void +x86emuOp2_movsx_word_R_RM(u8 X86EMU_UNUSED(op2)) +{ + int mod, rl, rh; + uint srcoffset; + u32 *destreg; + u32 srcval; + u16 *srcreg; + + START_OF_INSTR(); + DECODE_PRINTF("MOVSX\t"); + FETCH_DECODE_MODRM(mod, rh, rl); + switch (mod) { + case 0: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm00_address(rl); + srcval = (s32) ((s16) fetch_data_word(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 1: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm01_address(rl); + srcval = (s32) ((s16) fetch_data_word(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 2: + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcoffset = decode_rm10_address(rl); + srcval = (s32) ((s16) fetch_data_word(srcoffset)); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = srcval; + break; + case 3: /* register to register */ + destreg = DECODE_RM_LONG_REGISTER(rh); + DECODE_PRINTF(","); + srcreg = DECODE_RM_WORD_REGISTER(rl); + DECODE_PRINTF("\n"); + TRACE_AND_STEP(); + *destreg = (s32) ((s16) * srcreg); + break; + } + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/* Handles opcodes 0xc8-0xcf */ +static void +x86emuOp2_bswap(u8 X86EMU_UNUSED(op2)) +{ + START_OF_INSTR(); + DECODE_PRINTF("BSWAP\n"); + TRACE_AND_STEP(); + + switch (op2) { + case 0xc8: + M.x86.R_EAX = bswap_32(M.x86.R_EAX); + break; + case 0xc9: + M.x86.R_ECX = bswap_32(M.x86.R_ECX); + break; + case 0xca: + M.x86.R_EDX = bswap_32(M.x86.R_EDX); + break; + case 0xcb: + M.x86.R_EBX = bswap_32(M.x86.R_EBX); + break; + case 0xcc: + M.x86.R_ESP = bswap_32(M.x86.R_ESP); + break; + case 0xcd: + M.x86.R_EBP = bswap_32(M.x86.R_EBP); + break; + case 0xce: + M.x86.R_ESI = bswap_32(M.x86.R_ESI); + break; + case 0xcf: + M.x86.R_EDI = bswap_32(M.x86.R_EDI); + break; + default: + /* can't happen */ + break; + } + + DECODE_CLEAR_SEGOVR(); + END_OF_INSTR(); +} + +/*************************************************************************** + * Double byte operation code table: + **************************************************************************/ +void (*x86emu_optab2[256]) (u8) = { + /* 0x00 */ x86emuOp2_illegal_op, + /* Group F (ring 0 PM) */ + /* 0x01 */ x86emuOp2_illegal_op, + /* Group G (ring 0 PM) */ + /* 0x02 */ x86emuOp2_illegal_op, + /* lar (ring 0 PM) */ + /* 0x03 */ x86emuOp2_illegal_op, + /* lsl (ring 0 PM) */ +/* 0x04 */ x86emuOp2_illegal_op, + /* 0x05 */ x86emuOp2_illegal_op, + /* loadall (undocumented) */ + /* 0x06 */ x86emuOp2_illegal_op, + /* clts (ring 0 PM) */ + /* 0x07 */ x86emuOp2_illegal_op, + /* loadall (undocumented) */ + /* 0x08 */ x86emuOp2_illegal_op, + /* invd (ring 0 PM) */ + /* 0x09 */ x86emuOp2_illegal_op, + /* wbinvd (ring 0 PM) */ +/* 0x0a */ x86emuOp2_illegal_op, +/* 0x0b */ x86emuOp2_illegal_op, +/* 0x0c */ x86emuOp2_illegal_op, +/* 0x0d */ x86emuOp2_illegal_op, +/* 0x0e */ x86emuOp2_illegal_op, +/* 0x0f */ x86emuOp2_illegal_op, +/* 0x10 */ x86emuOp2_illegal_op, +/* 0x11 */ x86emuOp2_illegal_op, +/* 0x12 */ x86emuOp2_illegal_op, +/* 0x13 */ x86emuOp2_illegal_op, +/* 0x14 */ x86emuOp2_illegal_op, +/* 0x15 */ x86emuOp2_illegal_op, +/* 0x16 */ x86emuOp2_illegal_op, +/* 0x17 */ x86emuOp2_illegal_op, +/* 0x18 */ x86emuOp2_illegal_op, +/* 0x19 */ x86emuOp2_illegal_op, +/* 0x1a */ x86emuOp2_illegal_op, +/* 0x1b */ x86emuOp2_illegal_op, +/* 0x1c */ x86emuOp2_illegal_op, +/* 0x1d */ x86emuOp2_illegal_op, +/* 0x1e */ x86emuOp2_illegal_op, +/* 0x1f */ x86emuOp2_illegal_op, + /* 0x20 */ x86emuOp2_illegal_op, + /* mov reg32,creg (ring 0 PM) */ + /* 0x21 */ x86emuOp2_illegal_op, + /* mov reg32,dreg (ring 0 PM) */ + /* 0x22 */ x86emuOp2_illegal_op, + /* mov creg,reg32 (ring 0 PM) */ + /* 0x23 */ x86emuOp2_illegal_op, + /* mov dreg,reg32 (ring 0 PM) */ + /* 0x24 */ x86emuOp2_illegal_op, + /* mov reg32,treg (ring 0 PM) */ +/* 0x25 */ x86emuOp2_illegal_op, + /* 0x26 */ x86emuOp2_illegal_op, + /* mov treg,reg32 (ring 0 PM) */ +/* 0x27 */ x86emuOp2_illegal_op, +/* 0x28 */ x86emuOp2_illegal_op, +/* 0x29 */ x86emuOp2_illegal_op, +/* 0x2a */ x86emuOp2_illegal_op, +/* 0x2b */ x86emuOp2_illegal_op, +/* 0x2c */ x86emuOp2_illegal_op, +/* 0x2d */ x86emuOp2_illegal_op, +/* 0x2e */ x86emuOp2_illegal_op, +/* 0x2f */ x86emuOp2_illegal_op, +/* 0x30 */ x86emuOp2_illegal_op, +/* 0x31 */ x86emuOp2_rdtsc, +/* 0x32 */ x86emuOp2_illegal_op, +/* 0x33 */ x86emuOp2_illegal_op, +/* 0x34 */ x86emuOp2_illegal_op, +/* 0x35 */ x86emuOp2_illegal_op, +/* 0x36 */ x86emuOp2_illegal_op, +/* 0x37 */ x86emuOp2_illegal_op, +/* 0x38 */ x86emuOp2_illegal_op, +/* 0x39 */ x86emuOp2_illegal_op, +/* 0x3a */ x86emuOp2_illegal_op, +/* 0x3b */ x86emuOp2_illegal_op, +/* 0x3c */ x86emuOp2_illegal_op, +/* 0x3d */ x86emuOp2_illegal_op, +/* 0x3e */ x86emuOp2_illegal_op, +/* 0x3f */ x86emuOp2_illegal_op, +/* 0x40 */ x86emuOp2_illegal_op, +/* 0x41 */ x86emuOp2_illegal_op, +/* 0x42 */ x86emuOp2_illegal_op, +/* 0x43 */ x86emuOp2_illegal_op, +/* 0x44 */ x86emuOp2_illegal_op, +/* 0x45 */ x86emuOp2_illegal_op, +/* 0x46 */ x86emuOp2_illegal_op, +/* 0x47 */ x86emuOp2_illegal_op, +/* 0x48 */ x86emuOp2_illegal_op, +/* 0x49 */ x86emuOp2_illegal_op, +/* 0x4a */ x86emuOp2_illegal_op, +/* 0x4b */ x86emuOp2_illegal_op, +/* 0x4c */ x86emuOp2_illegal_op, +/* 0x4d */ x86emuOp2_illegal_op, +/* 0x4e */ x86emuOp2_illegal_op, +/* 0x4f */ x86emuOp2_illegal_op, +/* 0x50 */ x86emuOp2_illegal_op, +/* 0x51 */ x86emuOp2_illegal_op, +/* 0x52 */ x86emuOp2_illegal_op, +/* 0x53 */ x86emuOp2_illegal_op, +/* 0x54 */ x86emuOp2_illegal_op, +/* 0x55 */ x86emuOp2_illegal_op, +/* 0x56 */ x86emuOp2_illegal_op, +/* 0x57 */ x86emuOp2_illegal_op, +/* 0x58 */ x86emuOp2_illegal_op, +/* 0x59 */ x86emuOp2_illegal_op, +/* 0x5a */ x86emuOp2_illegal_op, +/* 0x5b */ x86emuOp2_illegal_op, +/* 0x5c */ x86emuOp2_illegal_op, +/* 0x5d */ x86emuOp2_illegal_op, +/* 0x5e */ x86emuOp2_illegal_op, +/* 0x5f */ x86emuOp2_illegal_op, +/* 0x60 */ x86emuOp2_illegal_op, +/* 0x61 */ x86emuOp2_illegal_op, +/* 0x62 */ x86emuOp2_illegal_op, +/* 0x63 */ x86emuOp2_illegal_op, +/* 0x64 */ x86emuOp2_illegal_op, +/* 0x65 */ x86emuOp2_illegal_op, +/* 0x66 */ x86emuOp2_illegal_op, +/* 0x67 */ x86emuOp2_illegal_op, +/* 0x68 */ x86emuOp2_illegal_op, +/* 0x69 */ x86emuOp2_illegal_op, +/* 0x6a */ x86emuOp2_illegal_op, +/* 0x6b */ x86emuOp2_illegal_op, +/* 0x6c */ x86emuOp2_illegal_op, +/* 0x6d */ x86emuOp2_illegal_op, +/* 0x6e */ x86emuOp2_illegal_op, +/* 0x6f */ x86emuOp2_illegal_op, +/* 0x70 */ x86emuOp2_illegal_op, +/* 0x71 */ x86emuOp2_illegal_op, +/* 0x72 */ x86emuOp2_illegal_op, +/* 0x73 */ x86emuOp2_illegal_op, +/* 0x74 */ x86emuOp2_illegal_op, +/* 0x75 */ x86emuOp2_illegal_op, +/* 0x76 */ x86emuOp2_illegal_op, +/* 0x77 */ x86emuOp2_illegal_op, +/* 0x78 */ x86emuOp2_illegal_op, +/* 0x79 */ x86emuOp2_illegal_op, +/* 0x7a */ x86emuOp2_illegal_op, +/* 0x7b */ x86emuOp2_illegal_op, +/* 0x7c */ x86emuOp2_illegal_op, +/* 0x7d */ x86emuOp2_illegal_op, +/* 0x7e */ x86emuOp2_illegal_op, +/* 0x7f */ x86emuOp2_illegal_op, +/* 0x80 */ x86emuOp2_long_jump, +/* 0x81 */ x86emuOp2_long_jump, +/* 0x82 */ x86emuOp2_long_jump, +/* 0x83 */ x86emuOp2_long_jump, +/* 0x84 */ x86emuOp2_long_jump, +/* 0x85 */ x86emuOp2_long_jump, +/* 0x86 */ x86emuOp2_long_jump, +/* 0x87 */ x86emuOp2_long_jump, +/* 0x88 */ x86emuOp2_long_jump, +/* 0x89 */ x86emuOp2_long_jump, +/* 0x8a */ x86emuOp2_long_jump, +/* 0x8b */ x86emuOp2_long_jump, +/* 0x8c */ x86emuOp2_long_jump, +/* 0x8d */ x86emuOp2_long_jump, +/* 0x8e */ x86emuOp2_long_jump, +/* 0x8f */ x86emuOp2_long_jump, +/* 0x90 */ x86emuOp2_set_byte, +/* 0x91 */ x86emuOp2_set_byte, +/* 0x92 */ x86emuOp2_set_byte, +/* 0x93 */ x86emuOp2_set_byte, +/* 0x94 */ x86emuOp2_set_byte, +/* 0x95 */ x86emuOp2_set_byte, +/* 0x96 */ x86emuOp2_set_byte, +/* 0x97 */ x86emuOp2_set_byte, +/* 0x98 */ x86emuOp2_set_byte, +/* 0x99 */ x86emuOp2_set_byte, +/* 0x9a */ x86emuOp2_set_byte, +/* 0x9b */ x86emuOp2_set_byte, +/* 0x9c */ x86emuOp2_set_byte, +/* 0x9d */ x86emuOp2_set_byte, +/* 0x9e */ x86emuOp2_set_byte, +/* 0x9f */ x86emuOp2_set_byte, +/* 0xa0 */ x86emuOp2_push_FS, +/* 0xa1 */ x86emuOp2_pop_FS, +/* 0xa2 */ x86emuOp2_cpuid, +/* 0xa3 */ x86emuOp2_bt_R, +/* 0xa4 */ x86emuOp2_shld_IMM, +/* 0xa5 */ x86emuOp2_shld_CL, +/* 0xa6 */ x86emuOp2_illegal_op, +/* 0xa7 */ x86emuOp2_illegal_op, +/* 0xa8 */ x86emuOp2_push_GS, +/* 0xa9 */ x86emuOp2_pop_GS, +/* 0xaa */ x86emuOp2_illegal_op, +/* 0xab */ x86emuOp2_bts_R, +/* 0xac */ x86emuOp2_shrd_IMM, +/* 0xad */ x86emuOp2_shrd_CL, +/* 0xae */ x86emuOp2_illegal_op, +/* 0xaf */ x86emuOp2_imul_R_RM, + /* 0xb0 */ x86emuOp2_illegal_op, + /* TODO: cmpxchg */ + /* 0xb1 */ x86emuOp2_illegal_op, + /* TODO: cmpxchg */ +/* 0xb2 */ x86emuOp2_lss_R_IMM, +/* 0xb3 */ x86emuOp2_btr_R, +/* 0xb4 */ x86emuOp2_lfs_R_IMM, +/* 0xb5 */ x86emuOp2_lgs_R_IMM, +/* 0xb6 */ x86emuOp2_movzx_byte_R_RM, +/* 0xb7 */ x86emuOp2_movzx_word_R_RM, +/* 0xb8 */ x86emuOp2_illegal_op, +/* 0xb9 */ x86emuOp2_illegal_op, +/* 0xba */ x86emuOp2_btX_I, +/* 0xbb */ x86emuOp2_btc_R, +/* 0xbc */ x86emuOp2_bsf, +/* 0xbd */ x86emuOp2_bsr, +/* 0xbe */ x86emuOp2_movsx_byte_R_RM, +/* 0xbf */ x86emuOp2_movsx_word_R_RM, + /* 0xc0 */ x86emuOp2_illegal_op, + /* TODO: xadd */ + /* 0xc1 */ x86emuOp2_illegal_op, + /* TODO: xadd */ +/* 0xc2 */ x86emuOp2_illegal_op, +/* 0xc3 */ x86emuOp2_illegal_op, +/* 0xc4 */ x86emuOp2_illegal_op, +/* 0xc5 */ x86emuOp2_illegal_op, +/* 0xc6 */ x86emuOp2_illegal_op, +/* 0xc7 */ x86emuOp2_illegal_op, +/* 0xc8 */ x86emuOp2_bswap, +/* 0xc9 */ x86emuOp2_bswap, +/* 0xca */ x86emuOp2_bswap, +/* 0xcb */ x86emuOp2_bswap, +/* 0xcc */ x86emuOp2_bswap, +/* 0xcd */ x86emuOp2_bswap, +/* 0xce */ x86emuOp2_bswap, +/* 0xcf */ x86emuOp2_bswap, +/* 0xd0 */ x86emuOp2_illegal_op, +/* 0xd1 */ x86emuOp2_illegal_op, +/* 0xd2 */ x86emuOp2_illegal_op, +/* 0xd3 */ x86emuOp2_illegal_op, +/* 0xd4 */ x86emuOp2_illegal_op, +/* 0xd5 */ x86emuOp2_illegal_op, +/* 0xd6 */ x86emuOp2_illegal_op, +/* 0xd7 */ x86emuOp2_illegal_op, +/* 0xd8 */ x86emuOp2_illegal_op, +/* 0xd9 */ x86emuOp2_illegal_op, +/* 0xda */ x86emuOp2_illegal_op, +/* 0xdb */ x86emuOp2_illegal_op, +/* 0xdc */ x86emuOp2_illegal_op, +/* 0xdd */ x86emuOp2_illegal_op, +/* 0xde */ x86emuOp2_illegal_op, +/* 0xdf */ x86emuOp2_illegal_op, +/* 0xe0 */ x86emuOp2_illegal_op, +/* 0xe1 */ x86emuOp2_illegal_op, +/* 0xe2 */ x86emuOp2_illegal_op, +/* 0xe3 */ x86emuOp2_illegal_op, +/* 0xe4 */ x86emuOp2_illegal_op, +/* 0xe5 */ x86emuOp2_illegal_op, +/* 0xe6 */ x86emuOp2_illegal_op, +/* 0xe7 */ x86emuOp2_illegal_op, +/* 0xe8 */ x86emuOp2_illegal_op, +/* 0xe9 */ x86emuOp2_illegal_op, +/* 0xea */ x86emuOp2_illegal_op, +/* 0xeb */ x86emuOp2_illegal_op, +/* 0xec */ x86emuOp2_illegal_op, +/* 0xed */ x86emuOp2_illegal_op, +/* 0xee */ x86emuOp2_illegal_op, +/* 0xef */ x86emuOp2_illegal_op, +/* 0xf0 */ x86emuOp2_illegal_op, +/* 0xf1 */ x86emuOp2_illegal_op, +/* 0xf2 */ x86emuOp2_illegal_op, +/* 0xf3 */ x86emuOp2_illegal_op, +/* 0xf4 */ x86emuOp2_illegal_op, +/* 0xf5 */ x86emuOp2_illegal_op, +/* 0xf6 */ x86emuOp2_illegal_op, +/* 0xf7 */ x86emuOp2_illegal_op, +/* 0xf8 */ x86emuOp2_illegal_op, +/* 0xf9 */ x86emuOp2_illegal_op, +/* 0xfa */ x86emuOp2_illegal_op, +/* 0xfb */ x86emuOp2_illegal_op, +/* 0xfc */ x86emuOp2_illegal_op, +/* 0xfd */ x86emuOp2_illegal_op, +/* 0xfe */ x86emuOp2_illegal_op, +/* 0xff */ x86emuOp2_illegal_op, +}; diff --git a/src/add-ons/kernel/generic/bios/x86emu/prim_ops.c b/src/add-ons/kernel/generic/bios/x86emu/prim_ops.c new file mode 100644 index 0000000000..24f76b47fb --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/prim_ops.c @@ -0,0 +1,2859 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file contains the code to implement the primitive +* machine operations used by the emulation code in ops.c +* +* Carry Chain Calculation +* +* This represents a somewhat expensive calculation which is +* apparently required to emulate the setting of the OF and AF flag. +* The latter is not so important, but the former is. The overflow +* flag is the XOR of the top two bits of the carry chain for an +* addition (similar for subtraction). Since we do not want to +* simulate the addition in a bitwise manner, we try to calculate the +* carry chain given the two operands and the result. +* +* So, given the following table, which represents the addition of two +* bits, we can derive a formula for the carry chain. +* +* a b cin r cout +* 0 0 0 0 0 +* 0 0 1 1 0 +* 0 1 0 1 0 +* 0 1 1 0 1 +* 1 0 0 1 0 +* 1 0 1 0 1 +* 1 1 0 0 1 +* 1 1 1 1 1 +* +* Construction of table for cout: +* +* ab +* r \ 00 01 11 10 +* |------------------ +* 0 | 0 1 1 1 +* 1 | 0 0 1 0 +* +* By inspection, one gets: cc = ab + r'(a + b) +* +* That represents alot of operations, but NO CHOICE.... +* +* Borrow Chain Calculation. +* +* The following table represents the subtraction of two bits, from +* which we can derive a formula for the borrow chain. +* +* a b bin r bout +* 0 0 0 0 0 +* 0 0 1 1 1 +* 0 1 0 1 1 +* 0 1 1 0 1 +* 1 0 0 1 0 +* 1 0 1 0 0 +* 1 1 0 0 0 +* 1 1 1 1 1 +* +* Construction of table for cout: +* +* ab +* r \ 00 01 11 10 +* |------------------ +* 0 | 0 1 0 0 +* 1 | 1 1 1 0 +* +* By inspection, one gets: bc = a'b + r(a' + b) +* +****************************************************************************/ + +#include + +#define PRIM_OPS_NO_REDEFINE_ASM +#include "x86emu/x86emui.h" + +#if defined(__GNUC__) +#if defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__) +#include "x86emu/prim_x86_gcc.h" +#endif +#endif + +/*------------------------- Global Variables ------------------------------*/ + +static u32 x86emu_parity_tab[8] = { + 0x96696996, + 0x69969669, + 0x69969669, + 0x96696996, + 0x69969669, + 0x96696996, + 0x96696996, + 0x69969669, +}; + +#define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) +#define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +REMARKS: +Implements the AAA instruction and side effects. +****************************************************************************/ +u16 +aaa_word(u16 d) +{ + u16 res; + + if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { + d += 0x6; + d += 0x100; + SET_FLAG(F_AF); + SET_FLAG(F_CF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + } + res = (u16) (d & 0xFF0F); + CLEAR_FLAG(F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the AAA instruction and side effects. +****************************************************************************/ +u16 +aas_word(u16 d) +{ + u16 res; + + if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) { + d -= 0x6; + d -= 0x100; + SET_FLAG(F_AF); + SET_FLAG(F_CF); + } + else { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + } + res = (u16) (d & 0xFF0F); + CLEAR_FLAG(F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the AAD instruction and side effects. +****************************************************************************/ +u16 +aad_word(u16 d) +{ + u16 l; + u8 hb, lb; + + hb = (u8) ((d >> 8) & 0xff); + lb = (u8) ((d & 0xff)); + l = (u16) ((lb + 10 * hb) & 0xFF); + + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(l & 0x80, F_SF); + CONDITIONAL_SET_FLAG(l == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); + return l; +} + +/**************************************************************************** +REMARKS: +Implements the AAM instruction and side effects. +****************************************************************************/ +u16 +aam_word(u8 d) +{ + u16 h, l; + + h = (u16) (d / 10); + l = (u16) (d % 10); + l |= (u16) (h << 8); + + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(l & 0x80, F_SF); + CONDITIONAL_SET_FLAG(l == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF); + return l; +} + +/**************************************************************************** +REMARKS: +Implements the ADC instruction and side effects. +****************************************************************************/ +u8 +adc_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + if (ACCESS_FLAG(F_CF)) + res = 1 + d + s; + else + res = d + s; + + CONDITIONAL_SET_FLAG(res & 0x100, F_CF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the ADC instruction and side effects. +****************************************************************************/ +u16 +adc_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + if (ACCESS_FLAG(F_CF)) + res = 1 + d + s; + else + res = d + s; + + CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the ADC instruction and side effects. +****************************************************************************/ +u32 +adc_long(u32 d, u32 s) +{ + register u32 lo; /* all operands in native machine order */ + register u32 hi; + register u32 res; + register u32 cc; + + if (ACCESS_FLAG(F_CF)) { + lo = 1 + (d & 0xFFFF) + (s & 0xFFFF); + res = 1 + d + s; + } + else { + lo = (d & 0xFFFF) + (s & 0xFFFF); + res = d + s; + } + hi = (lo >> 16) + (d >> 16) + (s >> 16); + + CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the ADD instruction and side effects. +****************************************************************************/ +u8 +add_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + res = d + s; + CONDITIONAL_SET_FLAG(res & 0x100, F_CF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the ADD instruction and side effects. +****************************************************************************/ +u16 +add_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + res = d + s; + CONDITIONAL_SET_FLAG(res & 0x10000, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the ADD instruction and side effects. +****************************************************************************/ +u32 +add_long(u32 d, u32 s) +{ + register u32 lo; /* all operands in native machine order */ + register u32 hi; + register u32 res; + register u32 cc; + + lo = (d & 0xFFFF) + (s & 0xFFFF); + res = d + s; + hi = (lo >> 16) + (d >> 16) + (s >> 16); + + CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (s & d) | ((~res) & (s | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + + return res; +} + +/**************************************************************************** +REMARKS: +Implements the AND instruction and side effects. +****************************************************************************/ +u8 +and_byte(u8 d, u8 s) +{ + register u8 res; /* all operands in native machine order */ + + res = d & s; + + /* set the flags */ + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the AND instruction and side effects. +****************************************************************************/ +u16 +and_word(u16 d, u16 s) +{ + register u16 res; /* all operands in native machine order */ + + res = d & s; + + /* set the flags */ + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the AND instruction and side effects. +****************************************************************************/ +u32 +and_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d & s; + + /* set the flags */ + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the CMP instruction and side effects. +****************************************************************************/ +u8 +cmp_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CLEAR_FLAG(F_CF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return d; +} + +/**************************************************************************** +REMARKS: +Implements the CMP instruction and side effects. +****************************************************************************/ +u16 +cmp_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return d; +} + +/**************************************************************************** +REMARKS: +Implements the CMP instruction and side effects. +****************************************************************************/ +u32 +cmp_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return d; +} + +/**************************************************************************** +REMARKS: +Implements the DAA instruction and side effects. +****************************************************************************/ +u8 +daa_byte(u8 d) +{ + u32 res = d; + + if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { + res += 6; + SET_FLAG(F_AF); + } + if (res > 0x9F || ACCESS_FLAG(F_CF)) { + res += 0x60; + SET_FLAG(F_CF); + } + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the DAS instruction and side effects. +****************************************************************************/ +u8 +das_byte(u8 d) +{ + if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) { + d -= 6; + SET_FLAG(F_AF); + } + if (d > 0x9F || ACCESS_FLAG(F_CF)) { + d -= 0x60; + SET_FLAG(F_CF); + } + CONDITIONAL_SET_FLAG(d & 0x80, F_SF); + CONDITIONAL_SET_FLAG(d == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF); + return d; +} + +/**************************************************************************** +REMARKS: +Implements the DEC instruction and side effects. +****************************************************************************/ +u8 +dec_byte(u8 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - 1; + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + /* based on sub_byte, uses s==1. */ + bc = (res & (~d | 1)) | (~d & 1); + /* carry flag unchanged */ + CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the DEC instruction and side effects. +****************************************************************************/ +u16 +dec_word(u16 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - 1; + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + /* based on the sub_byte routine, with s==1 */ + bc = (res & (~d | 1)) | (~d & 1); + /* carry flag unchanged */ + CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the DEC instruction and side effects. +****************************************************************************/ +u32 +dec_long(u32 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - 1; + + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | 1)) | (~d & 1); + /* carry flag unchanged */ + CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the INC instruction and side effects. +****************************************************************************/ +u8 +inc_byte(u8 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + res = d + 1; + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = ((1 & d) | (~res)) & (1 | d); + CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the INC instruction and side effects. +****************************************************************************/ +u16 +inc_word(u16 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + res = d + 1; + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (1 & d) | ((~res) & (1 | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the INC instruction and side effects. +****************************************************************************/ +u32 +inc_long(u32 d) +{ + register u32 res; /* all operands in native machine order */ + register u32 cc; + + res = d + 1; + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the carry chain SEE NOTE AT TOP. */ + cc = (1 & d) | ((~res) & (1 | d)); + CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF); + CONDITIONAL_SET_FLAG(cc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u8 +or_byte(u8 d, u8 s) +{ + register u8 res; /* all operands in native machine order */ + + res = d | s; + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u16 +or_word(u16 d, u16 s) +{ + register u16 res; /* all operands in native machine order */ + + res = d | s; + /* set the carry flag to be bit 8 */ + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u32 +or_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d | s; + + /* set the carry flag to be bit 8 */ + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u8 +neg_byte(u8 s) +{ + register u8 res; + register u8 bc; + + CONDITIONAL_SET_FLAG(s != 0, F_CF); + res = (u8) - s; + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res), F_PF); + /* calculate the borrow chain --- modified such that d=0. + substitutiing d=0 into bc= res&(~d|s)|(~d&s); + (the one used for sub) and simplifying, since ~d=0xff..., + ~d|s == 0xffff..., and res&0xfff... == res. Similarly + ~d&s == s. So the simplified result is: */ + bc = res | s; + CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u16 +neg_word(u16 s) +{ + register u16 res; + register u16 bc; + + CONDITIONAL_SET_FLAG(s != 0, F_CF); + res = (u16) - s; + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain --- modified such that d=0. + substitutiing d=0 into bc= res&(~d|s)|(~d&s); + (the one used for sub) and simplifying, since ~d=0xff..., + ~d|s == 0xffff..., and res&0xfff... == res. Similarly + ~d&s == s. So the simplified result is: */ + bc = res | s; + CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the OR instruction and side effects. +****************************************************************************/ +u32 +neg_long(u32 s) +{ + register u32 res; + register u32 bc; + + CONDITIONAL_SET_FLAG(s != 0, F_CF); + res = (u32) - s; + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain --- modified such that d=0. + substitutiing d=0 into bc= res&(~d|s)|(~d&s); + (the one used for sub) and simplifying, since ~d=0xff..., + ~d|s == 0xffff..., and res&0xfff... == res. Similarly + ~d&s == s. So the simplified result is: */ + bc = res | s; + CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the NOT instruction and side effects. +****************************************************************************/ +u8 +not_byte(u8 s) +{ + return ~s; +} + +/**************************************************************************** +REMARKS: +Implements the NOT instruction and side effects. +****************************************************************************/ +u16 +not_word(u16 s) +{ + return ~s; +} + +/**************************************************************************** +REMARKS: +Implements the NOT instruction and side effects. +****************************************************************************/ +u32 +not_long(u32 s) +{ + return ~s; +} + +/**************************************************************************** +REMARKS: +Implements the RCL instruction and side effects. +****************************************************************************/ +u8 +rcl_byte(u8 d, u8 s) +{ + register unsigned int res, cnt, mask, cf; + + /* s is the rotate distance. It varies from 0 - 8. */ + /* have + + CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 + + want to rotate through the carry by "s" bits. We could + loop, but that's inefficient. So the width is 9, + and we split into three parts: + + The new carry flag (was B_n) + the stuff in B_n-1 .. B_0 + the stuff in B_7 .. B_n+1 + + The new rotate is done mod 9, and given this, + for a rotation of n bits (mod 9) the new carry flag is + then located n bits from the MSB. The low part is + then shifted up cnt bits, and the high part is or'd + in. Using CAPS for new values, and lowercase for the + original values, this can be expressed as: + + IF n > 0 + 1) CF <- b_(8-n) + 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 + 3) B_(n-1) <- cf + 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) + */ + res = d; + if ((cnt = s % 9) != 0) { + /* extract the new CARRY FLAG. */ + /* CF <- b_(8-n) */ + cf = (d >> (8 - cnt)) & 0x1; + + /* get the low stuff which rotated + into the range B_7 .. B_cnt */ + /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */ + /* note that the right hand side done by the mask */ + res = (d << cnt) & 0xff; + + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */ + /* shift it downward, 7-(n-2) = 9-n positions. + and mask off the result before or'ing in. + */ + mask = (1 << (cnt - 1)) - 1; + res |= (d >> (9 - cnt)) & mask; + + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ + /* B_(n-1) <- cf */ + res |= 1 << (cnt - 1); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. */ + /* parenthesized this expression since it appears to + be causing OF to be misset */ + CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)), F_OF); + + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the RCL instruction and side effects. +****************************************************************************/ +u16 +rcl_word(u16 d, u8 s) +{ + register unsigned int res, cnt, mask, cf; + + res = d; + if ((cnt = s % 17) != 0) { + cf = (d >> (16 - cnt)) & 0x1; + res = (d << cnt) & 0xffff; + mask = (1 << (cnt - 1)) - 1; + res |= (d >> (17 - cnt)) & mask; + if (ACCESS_FLAG(F_CF)) { + res |= 1 << (cnt - 1); + } + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)), F_OF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the RCL instruction and side effects. +****************************************************************************/ +u32 +rcl_long(u32 d, u8 s) +{ + register u32 res, cnt, mask, cf; + + res = d; + if ((cnt = s % 33) != 0) { + cf = (d >> (32 - cnt)) & 0x1; + res = (d << cnt) & 0xffffffff; + mask = (1 << (cnt - 1)) - 1; + res |= (d >> (33 - cnt)) & mask; + if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ + res |= 1 << (cnt - 1); + } + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)), F_OF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the RCR instruction and side effects. +****************************************************************************/ +u8 +rcr_byte(u8 d, u8 s) +{ + u32 res, cnt; + u32 mask, cf, ocf = 0; + + /* rotate right through carry */ + /* + s is the rotate distance. It varies from 0 - 8. + d is the byte object rotated. + + have + + CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0 + + The new rotate is done mod 9, and given this, + for a rotation of n bits (mod 9) the new carry flag is + then located n bits from the LSB. The low part is + then shifted up cnt bits, and the high part is or'd + in. Using CAPS for new values, and lowercase for the + original values, this can be expressed as: + + IF n > 0 + 1) CF <- b_(n-1) + 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) + 3) B_(8-n) <- cf + 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) + */ + res = d; + if ((cnt = s % 9) != 0) { + /* extract the new CARRY FLAG. */ + /* CF <- b_(n-1) */ + if (cnt == 1) { + cf = d & 0x1; + /* note hackery here. Access_flag(..) evaluates to either + 0 if flag not set + non-zero if flag is set. + doing access_flag(..) != 0 casts that into either + 0..1 in any representation of the flags register + (i.e. packed bit array or unpacked.) + */ + ocf = ACCESS_FLAG(F_CF) != 0; + } + else + cf = (d >> (cnt - 1)) & 0x1; + + /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */ + /* note that the right hand side done by the mask + This is effectively done by shifting the + object to the right. The result must be masked, + in case the object came in and was treated + as a negative number. Needed??? */ + + mask = (1 << (8 - cnt)) - 1; + res = (d >> cnt) & mask; + + /* now the high stuff which rotated around + into the positions B_cnt-2 .. B_0 */ + /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */ + /* shift it downward, 7-(n-2) = 9-n positions. + and mask off the result before or'ing in. + */ + res |= (d << (9 - cnt)); + + /* if the carry flag was set, or it in. */ + if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ + /* B_(8-n) <- cf */ + res |= 1 << (8 - cnt); + } + /* set the new carry flag, based on the variable "cf" */ + CONDITIONAL_SET_FLAG(cf, F_CF); + /* OVERFLOW is set *IFF* cnt==1, then it is the + xor of CF and the most significant bit. Blecck. */ + /* parenthesized... */ + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)), F_OF); + } + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the RCR instruction and side effects. +****************************************************************************/ +u16 +rcr_word(u16 d, u8 s) +{ + u32 res, cnt; + u32 mask, cf, ocf = 0; + + /* rotate right through carry */ + res = d; + if ((cnt = s % 17) != 0) { + if (cnt == 1) { + cf = d & 0x1; + ocf = ACCESS_FLAG(F_CF) != 0; + } + else + cf = (d >> (cnt - 1)) & 0x1; + mask = (1 << (16 - cnt)) - 1; + res = (d >> cnt) & mask; + res |= (d << (17 - cnt)); + if (ACCESS_FLAG(F_CF)) { + res |= 1 << (16 - cnt); + } + CONDITIONAL_SET_FLAG(cf, F_CF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)), F_OF); + } + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the RCR instruction and side effects. +****************************************************************************/ +u32 +rcr_long(u32 d, u8 s) +{ + u32 res, cnt; + u32 mask, cf, ocf = 0; + + /* rotate right through carry */ + res = d; + if ((cnt = s % 33) != 0) { + if (cnt == 1) { + cf = d & 0x1; + ocf = ACCESS_FLAG(F_CF) != 0; + } + else + cf = (d >> (cnt - 1)) & 0x1; + mask = (1 << (32 - cnt)) - 1; + res = (d >> cnt) & mask; + if (cnt != 1) + res |= (d << (33 - cnt)); + if (ACCESS_FLAG(F_CF)) { /* carry flag is set */ + res |= 1 << (32 - cnt); + } + CONDITIONAL_SET_FLAG(cf, F_CF); + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)), F_OF); + } + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the ROL instruction and side effects. +****************************************************************************/ +u8 +rol_byte(u8 d, u8 s) +{ + register unsigned int res, cnt, mask; + + /* rotate left */ + /* + s is the rotate distance. It varies from 0 - 8. + d is the byte object rotated. + + have + + CF B_7 ... B_0 + + The new rotate is done mod 8. + Much simpler than the "rcl" or "rcr" operations. + + IF n > 0 + 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) + 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) + */ + res = d; + if ((cnt = s % 8) != 0) { + /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */ + res = (d << cnt); + + /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */ + mask = (1 << cnt) - 1; + res |= (d >> (8 - cnt)) & mask; + + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + /* OVERFLOW is set *IFF* s==1, then it is the + xor of CF and the most significant bit. Blecck. */ + CONDITIONAL_SET_FLAG(s == 1 && + XOR2((res & 0x1) + ((res >> 6) & 0x2)), F_OF); + } + if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the ROL instruction and side effects. +****************************************************************************/ +u16 +rol_word(u16 d, u8 s) +{ + register unsigned int res, cnt, mask; + + res = d; + if ((cnt = s % 16) != 0) { + res = (d << cnt); + mask = (1 << cnt) - 1; + res |= (d >> (16 - cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + CONDITIONAL_SET_FLAG(s == 1 && + XOR2((res & 0x1) + ((res >> 14) & 0x2)), F_OF); + } + if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the ROL instruction and side effects. +****************************************************************************/ +u32 +rol_long(u32 d, u8 s) +{ + register u32 res, cnt, mask; + + res = d; + if ((cnt = s % 32) != 0) { + res = (d << cnt); + mask = (1 << cnt) - 1; + res |= (d >> (32 - cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + CONDITIONAL_SET_FLAG(s == 1 && + XOR2((res & 0x1) + ((res >> 30) & 0x2)), F_OF); + } + if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x1, F_CF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the ROR instruction and side effects. +****************************************************************************/ +u8 +ror_byte(u8 d, u8 s) +{ + register unsigned int res, cnt, mask; + + /* rotate right */ + /* + s is the rotate distance. It varies from 0 - 8. + d is the byte object rotated. + + have + + B_7 ... B_0 + + The rotate is done mod 8. + + IF n > 0 + 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) + 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) + */ + res = d; + if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */ + /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */ + res = (d << (8 - cnt)); + + /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */ + mask = (1 << (8 - cnt)) - 1; + res |= (d >> (cnt)) & mask; + + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x80, F_CF); + /* OVERFLOW is set *IFF* s==1, then it is the + xor of the two most significant bits. Blecck. */ + CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF); + } + else if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x80, F_CF); + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the ROR instruction and side effects. +****************************************************************************/ +u16 +ror_word(u16 d, u8 s) +{ + register unsigned int res, cnt, mask; + + res = d; + if ((cnt = s % 16) != 0) { + res = (d << (16 - cnt)); + mask = (1 << (16 - cnt)) - 1; + res |= (d >> (cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); + CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF); + } + else if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x8000, F_CF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the ROR instruction and side effects. +****************************************************************************/ +u32 +ror_long(u32 d, u8 s) +{ + register u32 res, cnt, mask; + + res = d; + if ((cnt = s % 32) != 0) { + res = (d << (32 - cnt)); + mask = (1 << (32 - cnt)) - 1; + res |= (d >> (cnt)) & mask; + CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); + CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF); + } + else if (s != 0) { + /* set the new carry flag, Note that it is the low order + bit of the result!!! */ + CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SHL instruction and side effects. +****************************************************************************/ +u8 +shl_byte(u8 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 8) { + cnt = s % 8; + + /* last bit shifted out goes into carry flag */ + if (cnt > 0) { + res = d << cnt; + cf = d & (1 << (8 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = (u8) d; + } + + if (cnt == 1) { + /* Needs simplification. */ + CONDITIONAL_SET_FLAG((((res & 0x80) == 0x80) ^ + (ACCESS_FLAG(F_CF) != 0)), + /* was (M.x86.R_FLG&F_CF)==F_CF)), */ + F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHL instruction and side effects. +****************************************************************************/ +u16 +shl_word(u16 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + res = d << cnt; + cf = d & (1 << (16 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = (u16) d; + } + + if (cnt == 1) { + CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ + (ACCESS_FLAG(F_CF) != 0)), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHL instruction and side effects. +****************************************************************************/ +u32 +shl_long(u32 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 32) { + cnt = s % 32; + if (cnt > 0) { + res = d << cnt; + cf = d & (1 << (32 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + if (cnt == 1) { + CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ + (ACCESS_FLAG(F_CF) != 0)), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SHR instruction and side effects. +****************************************************************************/ +u8 +shr_byte(u8 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 8) { + cnt = s % 8; + if (cnt > 0) { + cf = d & (1 << (cnt - 1)); + res = d >> cnt; + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = (u8) d; + } + + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHR instruction and side effects. +****************************************************************************/ +u16 +shr_word(u16 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + cf = d & (1 << (cnt - 1)); + res = d >> cnt; + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHR instruction and side effects. +****************************************************************************/ +u32 +shr_long(u32 d, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 32) { + cnt = s % 32; + if (cnt > 0) { + cf = d & (1 << (cnt - 1)); + res = d >> cnt; + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SAR instruction and side effects. +****************************************************************************/ +u8 +sar_byte(u8 d, u8 s) +{ + unsigned int cnt, res, cf, mask, sf; + + res = d; + sf = d & 0x80; + cnt = s % 8; + if (cnt > 0 && cnt < 8) { + mask = (1 << (8 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, F_CF); + if (sf) { + res |= ~mask; + } + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + } + else if (cnt >= 8) { + if (sf) { + res = 0xff; + SET_FLAG(F_CF); + CLEAR_FLAG(F_ZF); + SET_FLAG(F_SF); + SET_FLAG(F_PF); + } + else { + res = 0; + CLEAR_FLAG(F_CF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + } + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the SAR instruction and side effects. +****************************************************************************/ +u16 +sar_word(u16 d, u8 s) +{ + unsigned int cnt, res, cf, mask, sf; + + sf = d & 0x8000; + cnt = s % 16; + res = d; + if (cnt > 0 && cnt < 16) { + mask = (1 << (16 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, F_CF); + if (sf) { + res |= ~mask; + } + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else if (cnt >= 16) { + if (sf) { + res = 0xffff; + SET_FLAG(F_CF); + CLEAR_FLAG(F_ZF); + SET_FLAG(F_SF); + SET_FLAG(F_PF); + } + else { + res = 0; + CLEAR_FLAG(F_CF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SAR instruction and side effects. +****************************************************************************/ +u32 +sar_long(u32 d, u8 s) +{ + u32 cnt, res, cf, mask, sf; + + sf = d & 0x80000000; + cnt = s % 32; + res = d; + if (cnt > 0 && cnt < 32) { + mask = (1 << (32 - cnt)) - 1; + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) & mask; + CONDITIONAL_SET_FLAG(cf, F_CF); + if (sf) { + res |= ~mask; + } + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else if (cnt >= 32) { + if (sf) { + res = 0xffffffff; + SET_FLAG(F_CF); + CLEAR_FLAG(F_ZF); + SET_FLAG(F_SF); + SET_FLAG(F_PF); + } + else { + res = 0; + CLEAR_FLAG(F_CF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SHLD instruction and side effects. +****************************************************************************/ +u16 +shld_word(u16 d, u16 fill, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + res = (d << cnt) | (fill >> (16 - cnt)); + cf = d & (1 << (16 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + if (cnt == 1) { + CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^ + (ACCESS_FLAG(F_CF) != 0)), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHLD instruction and side effects. +****************************************************************************/ +u32 +shld_long(u32 d, u32 fill, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 32) { + cnt = s % 32; + if (cnt > 0) { + res = (d << cnt) | (fill >> (32 - cnt)); + cf = d & (1 << (32 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + if (cnt == 1) { + CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^ + (ACCESS_FLAG(F_CF) != 0)), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF); + CLEAR_FLAG(F_OF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_PF); + SET_FLAG(F_ZF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SHRD instruction and side effects. +****************************************************************************/ +u16 +shrd_word(u16 d, u16 fill, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 16) { + cnt = s % 16; + if (cnt > 0) { + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) | (fill << (16 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SHRD instruction and side effects. +****************************************************************************/ +u32 +shrd_long(u32 d, u32 fill, u8 s) +{ + unsigned int cnt, res, cf; + + if (s < 32) { + cnt = s % 32; + if (cnt > 0) { + cf = d & (1 << (cnt - 1)); + res = (d >> cnt) | (fill << (32 - cnt)); + CONDITIONAL_SET_FLAG(cf, F_CF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + } + else { + res = d; + } + if (cnt == 1) { + CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF); + } + else { + CLEAR_FLAG(F_OF); + } + } + else { + res = 0; + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + SET_FLAG(F_ZF); + CLEAR_FLAG(F_SF); + CLEAR_FLAG(F_PF); + } + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SBB instruction and side effects. +****************************************************************************/ +u8 +sbb_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + if (ACCESS_FLAG(F_CF)) + res = d - s - 1; + else + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the SBB instruction and side effects. +****************************************************************************/ +u16 +sbb_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + if (ACCESS_FLAG(F_CF)) + res = d - s - 1; + else + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SBB instruction and side effects. +****************************************************************************/ +u32 +sbb_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + if (ACCESS_FLAG(F_CF)) + res = d - s - 1; + else + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the SUB instruction and side effects. +****************************************************************************/ +u8 +sub_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u8) res; +} + +/**************************************************************************** +REMARKS: +Implements the SUB instruction and side effects. +****************************************************************************/ +u16 +sub_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return (u16) res; +} + +/**************************************************************************** +REMARKS: +Implements the SUB instruction and side effects. +****************************************************************************/ +u32 +sub_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + register u32 bc; + + res = d - s; + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + + /* calculate the borrow chain. See note at top */ + bc = (res & (~d | s)) | (~d & s); + CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF); + CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF); + CONDITIONAL_SET_FLAG(bc & 0x8, F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the TEST instruction and side effects. +****************************************************************************/ +void +test_byte(u8 d, u8 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d & s; + + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + /* AF == dont care */ + CLEAR_FLAG(F_CF); +} + +/**************************************************************************** +REMARKS: +Implements the TEST instruction and side effects. +****************************************************************************/ +void +test_word(u16 d, u16 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d & s; + + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + /* AF == dont care */ + CLEAR_FLAG(F_CF); +} + +/**************************************************************************** +REMARKS: +Implements the TEST instruction and side effects. +****************************************************************************/ +void +test_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d & s; + + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + /* AF == dont care */ + CLEAR_FLAG(F_CF); +} + +/**************************************************************************** +REMARKS: +Implements the XOR instruction and side effects. +****************************************************************************/ +u8 +xor_byte(u8 d, u8 s) +{ + register u8 res; /* all operands in native machine order */ + + res = d ^ s; + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x80, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the XOR instruction and side effects. +****************************************************************************/ +u16 +xor_word(u16 d, u16 s) +{ + register u16 res; /* all operands in native machine order */ + + res = d ^ s; + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x8000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the XOR instruction and side effects. +****************************************************************************/ +u32 +xor_long(u32 d, u32 s) +{ + register u32 res; /* all operands in native machine order */ + + res = d ^ s; + CLEAR_FLAG(F_OF); + CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF); + CONDITIONAL_SET_FLAG(res == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF); + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + return res; +} + +/**************************************************************************** +REMARKS: +Implements the IMUL instruction and side effects. +****************************************************************************/ +void +imul_byte(u8 s) +{ + s16 res = (s16) ((s8) M.x86.R_AL * (s8) s); + + M.x86.R_AX = res; + if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) || + ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the IMUL instruction and side effects. +****************************************************************************/ +void +imul_word(u16 s) +{ + s32 res = (s16) M.x86.R_AX * (s16) s; + + M.x86.R_AX = (u16) res; + M.x86.R_DX = (u16) (res >> 16); + if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) || + ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the IMUL instruction and side effects. +****************************************************************************/ +void +imul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s) +{ +#ifdef __HAS_LONG_LONG__ + s64 res = (s64) (s32) d * (s32) s; + + *res_lo = (u32) res; + *res_hi = (u32) (res >> 32); +#else + u32 d_lo, d_hi, d_sign; + u32 s_lo, s_hi, s_sign; + u32 rlo_lo, rlo_hi, rhi_lo; + + if ((d_sign = d & 0x80000000) != 0) + d = -d; + d_lo = d & 0xFFFF; + d_hi = d >> 16; + if ((s_sign = s & 0x80000000) != 0) + s = -s; + s_lo = s & 0xFFFF; + s_hi = s >> 16; + rlo_lo = d_lo * s_lo; + rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16); + rhi_lo = d_hi * s_hi + (rlo_hi >> 16); + *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF); + *res_hi = rhi_lo; + if (d_sign != s_sign) { + d = ~*res_lo; + s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16); + *res_lo = ~*res_lo + 1; + *res_hi = ~*res_hi + (s >> 16); + } +#endif +} + +/**************************************************************************** +REMARKS: +Implements the IMUL instruction and side effects. +****************************************************************************/ +void +imul_long(u32 s) +{ + imul_long_direct(&M.x86.R_EAX, &M.x86.R_EDX, M.x86.R_EAX, s); + if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) || + ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the MUL instruction and side effects. +****************************************************************************/ +void +mul_byte(u8 s) +{ + u16 res = (u16) (M.x86.R_AL * s); + + M.x86.R_AX = res; + if (M.x86.R_AH == 0) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the MUL instruction and side effects. +****************************************************************************/ +void +mul_word(u16 s) +{ + u32 res = M.x86.R_AX * s; + + M.x86.R_AX = (u16) res; + M.x86.R_DX = (u16) (res >> 16); + if (M.x86.R_DX == 0) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the MUL instruction and side effects. +****************************************************************************/ +void +mul_long(u32 s) +{ +#ifdef __HAS_LONG_LONG__ + u64 res = (u64) M.x86.R_EAX * s; + + M.x86.R_EAX = (u32) res; + M.x86.R_EDX = (u32) (res >> 32); +#else + u32 a, a_lo, a_hi; + u32 s_lo, s_hi; + u32 rlo_lo, rlo_hi, rhi_lo; + + a = M.x86.R_EAX; + a_lo = a & 0xFFFF; + a_hi = a >> 16; + s_lo = s & 0xFFFF; + s_hi = s >> 16; + rlo_lo = a_lo * s_lo; + rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16); + rhi_lo = a_hi * s_hi + (rlo_hi >> 16); + M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF); + M.x86.R_EDX = rhi_lo; +#endif + + if (M.x86.R_EDX == 0) { + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_OF); + } + else { + SET_FLAG(F_CF); + SET_FLAG(F_OF); + } +} + +/**************************************************************************** +REMARKS: +Implements the IDIV instruction and side effects. +****************************************************************************/ +void +idiv_byte(u8 s) +{ + s32 dvd, div, mod; + + dvd = (s16) M.x86.R_AX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (s8) s; + mod = dvd % (s8) s; + if (abs(div) > 0x7f) { + x86emu_intr_raise(0); + return; + } + M.x86.R_AL = (s8) div; + M.x86.R_AH = (s8) mod; +} + +/**************************************************************************** +REMARKS: +Implements the IDIV instruction and side effects. +****************************************************************************/ +void +idiv_word(u16 s) +{ + s32 dvd, div, mod; + + dvd = (((s32) M.x86.R_DX) << 16) | M.x86.R_AX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (s16) s; + mod = dvd % (s16) s; + if (abs(div) > 0x7fff) { + x86emu_intr_raise(0); + return; + } + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_SF); + CONDITIONAL_SET_FLAG(div == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + M.x86.R_AX = (u16) div; + M.x86.R_DX = (u16) mod; +} + +/**************************************************************************** +REMARKS: +Implements the IDIV instruction and side effects. +****************************************************************************/ +void +idiv_long(u32 s) +{ +#ifdef __HAS_LONG_LONG__ + s64 dvd, div, mod; + + dvd = (((s64) M.x86.R_EDX) << 32) | M.x86.R_EAX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (s32) s; + mod = dvd % (s32) s; + if (abs(div) > 0x7fffffff) { + x86emu_intr_raise(0); + return; + } +#else + s32 div = 0, mod; + s32 h_dvd = M.x86.R_EDX; + u32 l_dvd = M.x86.R_EAX; + u32 abs_s = s & 0x7FFFFFFF; + u32 abs_h_dvd = h_dvd & 0x7FFFFFFF; + u32 h_s = abs_s >> 1; + u32 l_s = abs_s << 31; + int counter = 31; + int carry; + + if (s == 0) { + x86emu_intr_raise(0); + return; + } + do { + div <<= 1; + carry = (l_dvd >= l_s) ? 0 : 1; + + if (abs_h_dvd < (h_s + carry)) { + h_s >>= 1; + l_s = abs_s << (--counter); + continue; + } + else { + abs_h_dvd -= (h_s + carry); + l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) + : (l_dvd - l_s); + h_s >>= 1; + l_s = abs_s << (--counter); + div |= 1; + continue; + } + + } while (counter > -1); + /* overflow */ + if (abs_h_dvd || (l_dvd > abs_s)) { + x86emu_intr_raise(0); + return; + } + /* sign */ + div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000)); + mod = l_dvd; + +#endif + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + M.x86.R_EAX = (u32) div; + M.x86.R_EDX = (u32) mod; +} + +/**************************************************************************** +REMARKS: +Implements the DIV instruction and side effects. +****************************************************************************/ +void +div_byte(u8 s) +{ + u32 dvd, div, mod; + + dvd = M.x86.R_AX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (u8) s; + mod = dvd % (u8) s; + if (abs(div) > 0xff) { + x86emu_intr_raise(0); + return; + } + M.x86.R_AL = (u8) div; + M.x86.R_AH = (u8) mod; +} + +/**************************************************************************** +REMARKS: +Implements the DIV instruction and side effects. +****************************************************************************/ +void +div_word(u16 s) +{ + u32 dvd, div, mod; + + dvd = (((u32) M.x86.R_DX) << 16) | M.x86.R_AX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (u16) s; + mod = dvd % (u16) s; + if (abs(div) > 0xffff) { + x86emu_intr_raise(0); + return; + } + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_SF); + CONDITIONAL_SET_FLAG(div == 0, F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + M.x86.R_AX = (u16) div; + M.x86.R_DX = (u16) mod; +} + +/**************************************************************************** +REMARKS: +Implements the DIV instruction and side effects. +****************************************************************************/ +void +div_long(u32 s) +{ +#ifdef __HAS_LONG_LONG__ + u64 dvd, div, mod; + + dvd = (((u64) M.x86.R_EDX) << 32) | M.x86.R_EAX; + if (s == 0) { + x86emu_intr_raise(0); + return; + } + div = dvd / (u32) s; + mod = dvd % (u32) s; + if (abs(div) > 0xffffffff) { + x86emu_intr_raise(0); + return; + } +#else + s32 div = 0, mod; + s32 h_dvd = M.x86.R_EDX; + u32 l_dvd = M.x86.R_EAX; + + u32 h_s = s; + u32 l_s = 0; + int counter = 32; + int carry; + + if (s == 0) { + x86emu_intr_raise(0); + return; + } + do { + div <<= 1; + carry = (l_dvd >= l_s) ? 0 : 1; + + if (h_dvd < (h_s + carry)) { + h_s >>= 1; + l_s = s << (--counter); + continue; + } + else { + h_dvd -= (h_s + carry); + l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1) + : (l_dvd - l_s); + h_s >>= 1; + l_s = s << (--counter); + div |= 1; + continue; + } + + } while (counter > -1); + /* overflow */ + if (h_dvd || (l_dvd > s)) { + x86emu_intr_raise(0); + return; + } + mod = l_dvd; +#endif + CLEAR_FLAG(F_CF); + CLEAR_FLAG(F_AF); + CLEAR_FLAG(F_SF); + SET_FLAG(F_ZF); + CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF); + + M.x86.R_EAX = (u32) div; + M.x86.R_EDX = (u32) mod; +} + +/**************************************************************************** +REMARKS: +Implements the IN string instruction and side effects. +****************************************************************************/ +void +ins(int size) +{ + int inc = size; + + if (ACCESS_FLAG(F_DF)) { + inc = -size; + } + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* in until CX is ZERO. */ + u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? + M.x86.R_ECX : M.x86.R_CX); + switch (size) { + case 1: + while (count--) { + store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inb) (M.x86.R_DX)); + M.x86.R_DI += inc; + } + break; + + case 2: + while (count--) { + store_data_word_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inw) (M.x86.R_DX)); + M.x86.R_DI += inc; + } + break; + case 4: + while (count--) { + store_data_long_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inl) (M.x86.R_DX)); + M.x86.R_DI += inc; + break; + } + } + M.x86.R_CX = 0; + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = 0; + } + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + else { + switch (size) { + case 1: + store_data_byte_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inb) (M.x86.R_DX)); + break; + case 2: + store_data_word_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inw) (M.x86.R_DX)); + break; + case 4: + store_data_long_abs(M.x86.R_ES, M.x86.R_DI, + (*sys_inl) (M.x86.R_DX)); + break; + } + M.x86.R_DI += inc; + } +} + +/**************************************************************************** +REMARKS: +Implements the OUT string instruction and side effects. +****************************************************************************/ +void +outs(int size) +{ + int inc = size; + + if (ACCESS_FLAG(F_DF)) { + inc = -size; + } + if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) { + /* dont care whether REPE or REPNE */ + /* out until CX is ZERO. */ + u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ? + M.x86.R_ECX : M.x86.R_CX); + switch (size) { + case 1: + while (count--) { + (*sys_outb) (M.x86.R_DX, + fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); + M.x86.R_SI += inc; + } + break; + + case 2: + while (count--) { + (*sys_outw) (M.x86.R_DX, + fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); + M.x86.R_SI += inc; + } + break; + case 4: + while (count--) { + (*sys_outl) (M.x86.R_DX, + fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); + M.x86.R_SI += inc; + break; + } + } + M.x86.R_CX = 0; + if (M.x86.mode & SYSMODE_PREFIX_DATA) { + M.x86.R_ECX = 0; + } + M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE); + } + else { + switch (size) { + case 1: + (*sys_outb) (M.x86.R_DX, + fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI)); + break; + case 2: + (*sys_outw) (M.x86.R_DX, + fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI)); + break; + case 4: + (*sys_outl) (M.x86.R_DX, + fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI)); + break; + } + M.x86.R_SI += inc; + } +} + +/**************************************************************************** +PARAMETERS: +addr - Address to fetch word from + +REMARKS: +Fetches a word from emulator memory using an absolute address. +****************************************************************************/ +u16 +mem_access_word(int addr) +{ + DB(if (CHECK_MEM_ACCESS()) + x86emu_check_mem_access(addr);) + return (*sys_rdw) (addr); +} + +/**************************************************************************** +REMARKS: +Pushes a word onto the stack. + +NOTE: Do not inline this, as (*sys_wrX) is already inline! +****************************************************************************/ +void +push_word(u16 w) +{ + DB(if (CHECK_SP_ACCESS()) + x86emu_check_sp_access();) + M.x86.R_SP -= 2; + (*sys_wrw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w); +} + +/**************************************************************************** +REMARKS: +Pushes a long onto the stack. + +NOTE: Do not inline this, as (*sys_wrX) is already inline! +****************************************************************************/ +void +push_long(u32 w) +{ + DB(if (CHECK_SP_ACCESS()) + x86emu_check_sp_access();) + M.x86.R_SP -= 4; + (*sys_wrl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP, w); +} + +/**************************************************************************** +REMARKS: +Pops a word from the stack. + +NOTE: Do not inline this, as (*sys_rdX) is already inline! +****************************************************************************/ +u16 +pop_word(void) +{ + register u16 res; + + DB(if (CHECK_SP_ACCESS()) + x86emu_check_sp_access();) + res = (*sys_rdw) (((u32) M.x86.R_SS << 4) + M.x86.R_SP); + M.x86.R_SP += 2; + return res; +} + +/**************************************************************************** +REMARKS: +Pops a long from the stack. + +NOTE: Do not inline this, as (*sys_rdX) is already inline! +****************************************************************************/ +u32 +pop_long(void) +{ + register u32 res; + + DB(if (CHECK_SP_ACCESS()) + x86emu_check_sp_access();) + res = (*sys_rdl) (((u32) M.x86.R_SS << 4) + M.x86.R_SP); + M.x86.R_SP += 4; + return res; +} + +/**************************************************************************** +REMARKS: +CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output +****************************************************************************/ +void +cpuid(void) +{ + u32 feature = M.x86.R_EAX; + +#ifdef X86EMU_HAS_HW_CPUID + /* If the platform allows it, we will base our values on the real + * results from the CPUID instruction. We limit support to the + * first two features, and the results of those are sanitized. + */ + if (feature <= 1) + hw_cpuid(&M.x86.R_EAX, &M.x86.R_EBX, &M.x86.R_ECX, &M.x86.R_EDX); +#endif + + switch (feature) { + case 0: + /* Regardless if we have real data from the hardware, the emulator + * will only support upto feature 1, which we set in register EAX. + * Registers EBX:EDX:ECX contain a string identifying the CPU. + */ + M.x86.R_EAX = 1; +#ifndef X86EMU_HAS_HW_CPUID + /* EBX:EDX:ECX = "GenuineIntel" */ + M.x86.R_EBX = 0x756e6547; + M.x86.R_EDX = 0x49656e69; + M.x86.R_ECX = 0x6c65746e; +#endif + break; + case 1: +#ifndef X86EMU_HAS_HW_CPUID + /* If we don't have x86 compatible hardware, we return values from an + * Intel 486dx4; which was one of the first processors to have CPUID. + */ + M.x86.R_EAX = 0x00000480; + M.x86.R_EBX = 0x00000000; + M.x86.R_ECX = 0x00000000; + M.x86.R_EDX = 0x00000002; /* VME */ +#else + /* In the case that we have hardware CPUID instruction, we make sure + * that the features reported are limited to TSC and VME. + */ + M.x86.R_EDX &= 0x00000012; +#endif + break; + default: + /* Finally, we don't support any additional features. Most CPUs + * return all zeros when queried for invalid or unsupported feature + * numbers. + */ + M.x86.R_EAX = 0; + M.x86.R_EBX = 0; + M.x86.R_ECX = 0; + M.x86.R_EDX = 0; + break; + } +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/sys.c b/src/add-ons/kernel/generic/bios/x86emu/sys.c new file mode 100644 index 0000000000..031f44f534 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/sys.c @@ -0,0 +1,550 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: This file includes subroutines which are related to +* programmed I/O and memory access. Included in this module +* are default functions with limited usefulness. For real +* uses these functions will most likely be overriden by the +* user library. +* +****************************************************************************/ + +#include "x86emu.h" +#include "x86emu/x86emui.h" +#include "x86emu/regs.h" +#include "x86emu/debug.h" +#include "x86emu/prim_ops.h" +#ifndef NO_SYS_HEADERS +#include +#endif + +#ifdef __GNUC__ + +/* Define some packed structures to use with unaligned accesses */ + +struct __una_u64 { + u64 x __attribute__ ((packed)); +}; +struct __una_u32 { + u32 x __attribute__ ((packed)); +}; +struct __una_u16 { + u16 x __attribute__ ((packed)); +}; + +/* Elemental unaligned loads */ + +static __inline__ u64 +ldq_u(u64 * p) +{ + const struct __una_u64 *ptr = (const struct __una_u64 *) p; + + return ptr->x; +} + +static __inline__ u32 +ldl_u(u32 * p) +{ + const struct __una_u32 *ptr = (const struct __una_u32 *) p; + + return ptr->x; +} + +static __inline__ u16 +ldw_u(u16 * p) +{ + const struct __una_u16 *ptr = (const struct __una_u16 *) p; + + return ptr->x; +} + +/* Elemental unaligned stores */ + +static __inline__ void +stq_u(u64 val, u64 * p) +{ + struct __una_u64 *ptr = (struct __una_u64 *) p; + + ptr->x = val; +} + +static __inline__ void +stl_u(u32 val, u32 * p) +{ + struct __una_u32 *ptr = (struct __una_u32 *) p; + + ptr->x = val; +} + +static __inline__ void +stw_u(u16 val, u16 * p) +{ + struct __una_u16 *ptr = (struct __una_u16 *) p; + + ptr->x = val; +} +#else /* !__GNUC__ */ + +static __inline__ u64 +ldq_u(u64 * p) +{ + u64 ret; + + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ u32 +ldl_u(u32 * p) +{ + u32 ret; + + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ u16 +ldw_u(u16 * p) +{ + u16 ret; + + memmove(&ret, p, sizeof(*p)); + return ret; +} + +static __inline__ void +stq_u(u64 val, u64 * p) +{ + u64 tmp = val; + + memmove(p, &tmp, sizeof(*p)); +} + +static __inline__ void +stl_u(u32 val, u32 * p) +{ + u32 tmp = val; + + memmove(p, &tmp, sizeof(*p)); +} + +static __inline__ void +stw_u(u16 val, u16 * p) +{ + u16 tmp = val; + + memmove(p, &tmp, sizeof(*p)); +} + +#endif /* __GNUC__ */ +/*------------------------- Global Variables ------------------------------*/ + +X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ +X86EMU_intrFuncs _X86EMU_intrTab[256]; + +/*----------------------------- Implementation ----------------------------*/ + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Byte value read from emulator memory. + +REMARKS: +Reads a byte value from the emulator memory. +****************************************************************************/ +u8 X86API +rdb(u32 addr) +{ + u8 val; + + if (addr > M.mem_size - 1) { + DB(printk("mem_read: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } + val = *(u8 *) (M.mem_base + addr); + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 1 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Word value read from emulator memory. + +REMARKS: +Reads a word value from the emulator memory. +****************************************************************************/ +u16 X86API +rdw(u32 addr) +{ + u16 val = 0; + + if (addr > M.mem_size - 2) { + DB(printk("mem_read: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + val = (*(u8 *) (M.mem_base + addr) | + (*(u8 *) (M.mem_base + addr + 1) << 8)); + } + else +#endif + val = ldw_u((u16 *) (M.mem_base + addr)); + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 2 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read + +RETURNS: +Long value read from emulator memory. +REMARKS: +Reads a long value from the emulator memory. +****************************************************************************/ +u32 X86API +rdl(u32 addr) +{ + u32 val = 0; + + if (addr > M.mem_size - 4) { + DB(printk("mem_read: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } +#ifdef __BIG_ENDIAN__ + if (addr & 0x3) { + val = (*(u8 *) (M.mem_base + addr + 0) | + (*(u8 *) (M.mem_base + addr + 1) << 8) | + (*(u8 *) (M.mem_base + addr + 2) << 16) | + (*(u8 *) (M.mem_base + addr + 3) << 24)); + } + else +#endif + val = ldl_u((u32 *) (M.mem_base + addr)); + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 4 -> %#x\n", addr, val);) + return val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a byte value to emulator memory. +****************************************************************************/ +void X86API +wrb(u32 addr, u8 val) +{ + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 1 <- %#x\n", addr, val);) + if (addr > M.mem_size - 1) { + DB(printk("mem_write: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } + *(u8 *) (M.mem_base + addr) = val; +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a word value to emulator memory. +****************************************************************************/ +void X86API +wrw(u32 addr, u16 val) +{ + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 2 <- %#x\n", addr, val);) + if (addr > M.mem_size - 2) { + DB(printk("mem_write: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff; + *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff; + } + else +#endif + stw_u(val, (u16 *) (M.mem_base + addr)); +} + +/**************************************************************************** +PARAMETERS: +addr - Emulator memory address to read +val - Value to store + +REMARKS: +Writes a long value to emulator memory. +****************************************************************************/ +void X86API +wrl(u32 addr, u32 val) +{ + DB(if (DEBUG_MEM_TRACE()) + printk("%#08x 4 <- %#x\n", addr, val);) + if (addr > M.mem_size - 4) { + DB(printk("mem_write: address %#x out of range!\n", addr); + ) + HALT_SYS(); + } +#ifdef __BIG_ENDIAN__ + if (addr & 0x1) { + *(u8 *) (M.mem_base + addr + 0) = (val >> 0) & 0xff; + *(u8 *) (M.mem_base + addr + 1) = (val >> 8) & 0xff; + *(u8 *) (M.mem_base + addr + 2) = (val >> 16) & 0xff; + *(u8 *) (M.mem_base + addr + 3) = (val >> 24) & 0xff; + } + else +#endif + stl_u(val, (u32 *) (M.mem_base + addr)); +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to read +RETURN: +0 +REMARKS: +Default PIO byte read function. Doesn't perform real inb. +****************************************************************************/ +static u8 X86API +p_inb(X86EMU_pioAddr addr) +{ + DB(if (DEBUG_IO_TRACE()) + printk("inb %#04x \n", addr);) + return 0; +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to read +RETURN: +0 +REMARKS: +Default PIO word read function. Doesn't perform real inw. +****************************************************************************/ +static u16 X86API +p_inw(X86EMU_pioAddr addr) +{ + DB(if (DEBUG_IO_TRACE()) + printk("inw %#04x \n", addr);) + return 0; +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to read +RETURN: +0 +REMARKS: +Default PIO long read function. Doesn't perform real inl. +****************************************************************************/ +static u32 X86API +p_inl(X86EMU_pioAddr addr) +{ + DB(if (DEBUG_IO_TRACE()) + printk("inl %#04x \n", addr);) + return 0; +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to write +val - Value to store +REMARKS: +Default PIO byte write function. Doesn't perform real outb. +****************************************************************************/ +static void X86API +p_outb(X86EMU_pioAddr addr, u8 val) +{ + DB(if (DEBUG_IO_TRACE()) + printk("outb %#02x -> %#04x \n", val, addr);) + return; +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to write +val - Value to store +REMARKS: +Default PIO word write function. Doesn't perform real outw. +****************************************************************************/ +static void X86API +p_outw(X86EMU_pioAddr addr, u16 val) +{ + DB(if (DEBUG_IO_TRACE()) + printk("outw %#04x -> %#04x \n", val, addr);) + return; +} + +/**************************************************************************** +PARAMETERS: +addr - PIO address to write +val - Value to store +REMARKS: +Default PIO ;ong write function. Doesn't perform real outl. +****************************************************************************/ +static void X86API +p_outl(X86EMU_pioAddr addr, u32 val) +{ + DB(if (DEBUG_IO_TRACE()) + printk("outl %#08x -> %#04x \n", val, addr);) + return; +} + +/*------------------------- Global Variables ------------------------------*/ + +u8(X86APIP sys_rdb) (u32 addr) = rdb; +u16(X86APIP sys_rdw) (u32 addr) = rdw; +u32(X86APIP sys_rdl) (u32 addr) = rdl; +void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb; +void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw; +void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl; + +u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb; +u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw; +u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl; +void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb; +void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw; +void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl; + +/*----------------------------- Setup -------------------------------------*/ + +/**************************************************************************** +PARAMETERS: +funcs - New memory function pointers to make active + +REMARKS: +This function is used to set the pointers to functions which access +memory space, allowing the user application to override these functions +and hook them out as necessary for their application. +****************************************************************************/ +void +X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs) +{ + sys_rdb = funcs->rdb; + sys_rdw = funcs->rdw; + sys_rdl = funcs->rdl; + sys_wrb = funcs->wrb; + sys_wrw = funcs->wrw; + sys_wrl = funcs->wrl; +} + +/**************************************************************************** +PARAMETERS: +funcs - New programmed I/O function pointers to make active + +REMARKS: +This function is used to set the pointers to functions which access +I/O space, allowing the user application to override these functions +and hook them out as necessary for their application. +****************************************************************************/ +void +X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs) +{ + sys_inb = funcs->inb; + sys_inw = funcs->inw; + sys_inl = funcs->inl; + sys_outb = funcs->outb; + sys_outw = funcs->outw; + sys_outl = funcs->outl; +} + +/**************************************************************************** +PARAMETERS: +funcs - New interrupt vector table to make active + +REMARKS: +This function is used to set the pointers to functions which handle +interrupt processing in the emulator, allowing the user application to +hook interrupts as necessary for their application. Any interrupts that +are not hooked by the user application, and reflected and handled internally +in the emulator via the interrupt vector table. This allows the application +to get control when the code being emulated executes specific software +interrupts. +****************************************************************************/ +void +X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]) +{ + int i; + + for (i = 0; i < 256; i++) + _X86EMU_intrTab[i] = NULL; + if (funcs) { + for (i = 0; i < 256; i++) + _X86EMU_intrTab[i] = funcs[i]; + } +} + +/**************************************************************************** +PARAMETERS: +int - New software interrupt to prepare for + +REMARKS: +This function is used to set up the emulator state to exceute a software +interrupt. This can be used by the user application code to allow an +interrupt to be hooked, examined and then reflected back to the emulator +so that the code in the emulator will continue processing the software +interrupt as per normal. This essentially allows system code to actively +hook and handle certain software interrupts as necessary. +****************************************************************************/ +void +X86EMU_prepareForInt(int num) +{ + push_word((u16) M.x86.R_FLG); + CLEAR_FLAG(F_IF); + CLEAR_FLAG(F_TF); + push_word(M.x86.R_CS); + M.x86.R_CS = mem_access_word(num * 4 + 2); + push_word(M.x86.R_IP); + M.x86.R_IP = mem_access_word(num * 4); + M.x86.intr = 0; +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/validate.c b/src/add-ons/kernel/generic/bios/x86emu/validate.c new file mode 100644 index 0000000000..4c36e1df51 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/validate.c @@ -0,0 +1,769 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: Watcom C 10.6 or later +* Environment: 32-bit DOS +* Developer: Kendall Bennett +* +* Description: Program to validate the x86 emulator library for +* correctness. We run the emulator primitive operations +* functions against the real x86 CPU, and compare the result +* and flags to ensure correctness. +* +* We use inline assembler to compile and build this program. +* +****************************************************************************/ + +#include +#include +#include +#include +#include "x86emu.h" +#include "x86emu/prim_asm.h" + +/*-------------------------- Implementation -------------------------------*/ + +#define true 1 +#define false 0 + +#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF) + +#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \ +{ \ + parm_type d,s; \ + res_type r,r_asm; \ + ulong flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < dmax; d += dincr) { \ + for (s = 0; s < smax; s += sincr) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { + +#define VAL_TEST_BINARY(name) \ + r_asm = name##_asm(&flags,d,s); \ + r = name(d,s); \ + if (r != r_asm || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { + +#define VAL_TEST_BINARY_VOID(name) \ + name##_asm(&flags,d,s); \ + name(d,s); \ + r = r_asm = 0; \ + if (M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { + +#define VAL_FAIL_BYTE_BYTE_BINARY(name) \ + if (failed) \ + printk("fail\n"); \ + printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ + r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_FAIL_WORD_WORD_BINARY(name) \ + if (failed) \ + printk("fail\n"); \ + printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ + r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_FAIL_LONG_LONG_BINARY(name) \ + if (failed) \ + printk("fail\n"); \ + printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ + r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_END_BINARY() \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_BYTE_BYTE_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_BYTE_BYTE_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_WORD_WORD_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_WORD_WORD_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_LONG_LONG_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_LONG_LONG_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_VOID_BYTE_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \ + VAL_TEST_BINARY_VOID(name) \ + VAL_FAIL_BYTE_BYTE_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_VOID_WORD_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \ + VAL_TEST_BINARY_VOID(name) \ + VAL_FAIL_WORD_WORD_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_VOID_LONG_BINARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \ + VAL_TEST_BINARY_VOID(name) \ + VAL_FAIL_LONG_LONG_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_BYTE_ROTATE(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u8,u8,0xFF,8,1,1) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_BYTE_BYTE_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_WORD_ROTATE(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_WORD_WORD_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_LONG_ROTATE(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \ + VAL_TEST_BINARY(name) \ + VAL_FAIL_LONG_LONG_BINARY(name) \ + VAL_END_BINARY() + +#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\ +{ \ + parm_type d,s; \ + res_type r,r_asm; \ + u8 shift; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < dmax; d += dincr) { \ + for (s = 0; s < smax; s += sincr) { \ + for (shift = 0; shift < maxshift; shift += 1) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { + +#define VAL_TEST_TERNARY(name) \ + r_asm = name##_asm(&flags,d,s,shift); \ + r = name(d,s,shift); \ + if (r != r_asm || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { + +#define VAL_FAIL_WORD_WORD_TERNARY(name) \ + if (failed) \ + printk("fail\n"); \ + printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ + r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_FAIL_LONG_LONG_TERNARY(name) \ + if (failed) \ + printk("fail\n"); \ + printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ + r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_END_TERNARY() \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_WORD_ROTATE_DBL(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \ + VAL_TEST_TERNARY(name) \ + VAL_FAIL_WORD_WORD_TERNARY(name) \ + VAL_END_TERNARY() + +#define VAL_LONG_ROTATE_DBL(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \ + VAL_TEST_TERNARY(name) \ + VAL_FAIL_LONG_LONG_TERNARY(name) \ + VAL_END_TERNARY() + +#define VAL_START_UNARY(parm_type,max,incr) \ +{ \ + parm_type d,r,r_asm; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < max; d += incr) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { + +#define VAL_TEST_UNARY(name) \ + r_asm = name##_asm(&flags,d); \ + r = name(d); \ + if (r != r_asm || M.x86.R_EFLG != flags) { \ + failed = true; + +#define VAL_FAIL_BYTE_UNARY(name) \ + printk("fail\n"); \ + printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ + r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_FAIL_WORD_UNARY(name) \ + printk("fail\n"); \ + printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ + r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_FAIL_LONG_UNARY(name) \ + printk("fail\n"); \ + printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ + r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags)); + +#define VAL_END_UNARY() \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_BYTE_UNARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_UNARY(u8,0xFF,0x1) \ + VAL_TEST_UNARY(name) \ + VAL_FAIL_BYTE_UNARY(name) \ + VAL_END_UNARY() + +#define VAL_WORD_UNARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_UNARY(u16,0xFF00,0x100) \ + VAL_TEST_UNARY(name) \ + VAL_FAIL_WORD_UNARY(name) \ + VAL_END_UNARY() + +#define VAL_WORD_BYTE_UNARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_UNARY(u16,0xFF,0x1) \ + VAL_TEST_UNARY(name) \ + VAL_FAIL_WORD_UNARY(name) \ + VAL_END_UNARY() + +#define VAL_LONG_UNARY(name) \ + printk("Validating %s ... ", #name); \ + VAL_START_UNARY(u32,0xFF000000,0x1000000) \ + VAL_TEST_UNARY(name) \ + VAL_FAIL_LONG_UNARY(name) \ + VAL_END_UNARY() + +#define VAL_BYTE_MUL(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u8 d,s; \ + u16 r,r_asm; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF; d += 1) { \ + for (s = 0; s < 0xFF; s += 1) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + name##_asm(&flags,&r_asm,d,s); \ + M.x86.R_AL = d; \ + name(s); \ + r = M.x86.R_AX; \ + if (r != r_asm || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ + r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \ + r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_WORD_MUL(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u16 d,s; \ + u16 r_lo,r_asm_lo; \ + u16 r_hi,r_asm_hi; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF00; d += 0x100) { \ + for (s = 0; s < 0xFF00; s += 0x100) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ + M.x86.R_AX = d; \ + name(s); \ + r_lo = M.x86.R_AX; \ + r_hi = M.x86.R_DX; \ + if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ + r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \ + r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_LONG_MUL(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u32 d,s; \ + u32 r_lo,r_asm_lo; \ + u32 r_hi,r_asm_hi; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF000000; d += 0x1000000) { \ + for (s = 0; s < 0xFF000000; s += 0x1000000) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \ + M.x86.R_EAX = d; \ + name(s); \ + r_lo = M.x86.R_EAX; \ + r_hi = M.x86.R_EDX; \ + if (r_lo != r_asm_lo || r_hi != r_asm_hi || M.x86.R_EFLG != flags)\ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ + r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \ + r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_BYTE_DIV(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u16 d,s; \ + u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF00; d += 0x100) { \ + for (s = 1; s < 0xFF; s += 1) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + M.x86.intr = 0; \ + M.x86.R_AX = d; \ + name(s); \ + r_quot = M.x86.R_AL; \ + r_rem = M.x86.R_AH; \ + if (M.x86.intr & INTR_SYNCH) \ + continue; \ + name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \ + if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ + r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \ + r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_WORD_DIV(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u32 d,s; \ + u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF000000; d += 0x1000000) { \ + for (s = 0x100; s < 0xFF00; s += 0x100) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + M.x86.intr = 0; \ + M.x86.R_AX = d & 0xFFFF; \ + M.x86.R_DX = d >> 16; \ + name(s); \ + r_quot = M.x86.R_AX; \ + r_rem = M.x86.R_DX; \ + if (M.x86.intr & INTR_SYNCH) \ + continue; \ + name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\ + if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ + r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \ + r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +#define VAL_LONG_DIV(name) \ + printk("Validating %s ... ", #name); \ +{ \ + u32 d,s; \ + u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \ + u32 flags,inflags; \ + int f,failed = false; \ + char buf1[80],buf2[80]; \ + for (d = 0; d < 0xFF000000; d += 0x1000000) { \ + for (s = 0x100; s < 0xFF00; s += 0x100) { \ + M.x86.R_EFLG = inflags = flags = def_flags; \ + for (f = 0; f < 2; f++) { \ + M.x86.intr = 0; \ + M.x86.R_EAX = d; \ + M.x86.R_EDX = 0; \ + name(s); \ + r_quot = M.x86.R_EAX; \ + r_rem = M.x86.R_EDX; \ + if (M.x86.intr & INTR_SYNCH) \ + continue; \ + name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \ + if (r_quot != r_asm_quot || r_rem != r_asm_rem || M.x86.R_EFLG != flags) \ + failed = true; \ + if (failed || trace) { \ + if (failed) \ + printk("fail\n"); \ + printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ + r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \ + printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \ + r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \ + } \ + M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (failed) \ + break; \ + } \ + if (!failed) \ + printk("passed\n"); \ +} + +void +printk(const char *fmt, ...) +{ + va_list argptr; + + va_start(argptr, fmt); + vfprintf(stdout, fmt, argptr); + fflush(stdout); + va_end(argptr); +} + +char * +print_flags(char *buf, ulong flags) +{ + char *separator = ""; + + buf[0] = 0; + if (flags & F_CF) { + strcat(buf, separator); + strcat(buf, "CF"); + separator = ","; + } + if (flags & F_PF) { + strcat(buf, separator); + strcat(buf, "PF"); + separator = ","; + } + if (flags & F_AF) { + strcat(buf, separator); + strcat(buf, "AF"); + separator = ","; + } + if (flags & F_ZF) { + strcat(buf, separator); + strcat(buf, "ZF"); + separator = ","; + } + if (flags & F_SF) { + strcat(buf, separator); + strcat(buf, "SF"); + separator = ","; + } + if (flags & F_OF) { + strcat(buf, separator); + strcat(buf, "OF"); + separator = ","; + } + if (separator[0] == 0) + strcpy(buf, "None"); + return buf; +} + +int +main(int argc) +{ + ulong def_flags; + int trace = false; + + if (argc > 1) + trace = true; + memset(&M, 0, sizeof(M)); + def_flags = get_flags_asm() & ~ALL_FLAGS; + + VAL_WORD_UNARY(aaa_word); + VAL_WORD_UNARY(aas_word); + + VAL_WORD_UNARY(aad_word); + VAL_WORD_UNARY(aam_word); + + VAL_BYTE_BYTE_BINARY(adc_byte); + VAL_WORD_WORD_BINARY(adc_word); + VAL_LONG_LONG_BINARY(adc_long); + + VAL_BYTE_BYTE_BINARY(add_byte); + VAL_WORD_WORD_BINARY(add_word); + VAL_LONG_LONG_BINARY(add_long); + + VAL_BYTE_BYTE_BINARY(and_byte); + VAL_WORD_WORD_BINARY(and_word); + VAL_LONG_LONG_BINARY(and_long); + + VAL_BYTE_BYTE_BINARY(cmp_byte); + VAL_WORD_WORD_BINARY(cmp_word); + VAL_LONG_LONG_BINARY(cmp_long); + + VAL_BYTE_UNARY(daa_byte); + VAL_BYTE_UNARY(das_byte); /* Fails for 0x9A (out of range anyway) */ + + VAL_BYTE_UNARY(dec_byte); + VAL_WORD_UNARY(dec_word); + VAL_LONG_UNARY(dec_long); + + VAL_BYTE_UNARY(inc_byte); + VAL_WORD_UNARY(inc_word); + VAL_LONG_UNARY(inc_long); + + VAL_BYTE_BYTE_BINARY(or_byte); + VAL_WORD_WORD_BINARY(or_word); + VAL_LONG_LONG_BINARY(or_long); + + VAL_BYTE_UNARY(neg_byte); + VAL_WORD_UNARY(neg_word); + VAL_LONG_UNARY(neg_long); + + VAL_BYTE_UNARY(not_byte); + VAL_WORD_UNARY(not_word); + VAL_LONG_UNARY(not_long); + + VAL_BYTE_ROTATE(rcl_byte); + VAL_WORD_ROTATE(rcl_word); + VAL_LONG_ROTATE(rcl_long); + + VAL_BYTE_ROTATE(rcr_byte); + VAL_WORD_ROTATE(rcr_word); + VAL_LONG_ROTATE(rcr_long); + + VAL_BYTE_ROTATE(rol_byte); + VAL_WORD_ROTATE(rol_word); + VAL_LONG_ROTATE(rol_long); + + VAL_BYTE_ROTATE(ror_byte); + VAL_WORD_ROTATE(ror_word); + VAL_LONG_ROTATE(ror_long); + + VAL_BYTE_ROTATE(shl_byte); + VAL_WORD_ROTATE(shl_word); + VAL_LONG_ROTATE(shl_long); + + VAL_BYTE_ROTATE(shr_byte); + VAL_WORD_ROTATE(shr_word); + VAL_LONG_ROTATE(shr_long); + + VAL_BYTE_ROTATE(sar_byte); + VAL_WORD_ROTATE(sar_word); + VAL_LONG_ROTATE(sar_long); + + VAL_WORD_ROTATE_DBL(shld_word); + VAL_LONG_ROTATE_DBL(shld_long); + + VAL_WORD_ROTATE_DBL(shrd_word); + VAL_LONG_ROTATE_DBL(shrd_long); + + VAL_BYTE_BYTE_BINARY(sbb_byte); + VAL_WORD_WORD_BINARY(sbb_word); + VAL_LONG_LONG_BINARY(sbb_long); + + VAL_BYTE_BYTE_BINARY(sub_byte); + VAL_WORD_WORD_BINARY(sub_word); + VAL_LONG_LONG_BINARY(sub_long); + + VAL_BYTE_BYTE_BINARY(xor_byte); + VAL_WORD_WORD_BINARY(xor_word); + VAL_LONG_LONG_BINARY(xor_long); + + VAL_VOID_BYTE_BINARY(test_byte); + VAL_VOID_WORD_BINARY(test_word); + VAL_VOID_LONG_BINARY(test_long); + + VAL_BYTE_MUL(imul_byte); + VAL_WORD_MUL(imul_word); + VAL_LONG_MUL(imul_long); + + VAL_BYTE_MUL(mul_byte); + VAL_WORD_MUL(mul_word); + VAL_LONG_MUL(mul_long); + + VAL_BYTE_DIV(idiv_byte); + VAL_WORD_DIV(idiv_word); + VAL_LONG_DIV(idiv_long); + + VAL_BYTE_DIV(div_byte); + VAL_WORD_DIV(div_word); + VAL_LONG_DIV(div_long); + + return 0; +} diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu.h new file mode 100644 index 0000000000..501dd913c9 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu.h @@ -0,0 +1,197 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for public specific functions. +* Any application linking against us should only +* include this header +* +****************************************************************************/ + +#ifndef __X86EMU_X86EMU_H +#define __X86EMU_X86EMU_H + +#ifdef SCITECH +#include "scitech.h" +#define X86API _ASMAPI +#define X86APIP _ASMAPIP +typedef int X86EMU_pioAddr; +#else +#include "x86emu/types.h" +#define X86API +#define X86APIP * +#endif +#include "x86emu/regs.h" + +/*---------------------- Macros and type definitions ----------------------*/ + +#ifdef PACK +#pragma PACK /* Don't pack structs with function pointers! */ +#endif + +/**************************************************************************** +REMARKS: +Data structure containing ponters to programmed I/O functions used by the +emulator. This is used so that the user program can hook all programmed +I/O for the emulator to handled as necessary by the user program. By +default the emulator contains simple functions that do not do access the +hardware in any way. To allow the emualtor access the hardware, you will +need to override the programmed I/O functions using the X86EMU_setupPioFuncs +function. + +HEADER: +x86emu.h + +MEMBERS: +inb - Function to read a byte from an I/O port +inw - Function to read a word from an I/O port +inl - Function to read a dword from an I/O port +outb - Function to write a byte to an I/O port +outw - Function to write a word to an I/O port +outl - Function to write a dword to an I/O port +****************************************************************************/ +typedef struct { + u8(X86APIP inb) (X86EMU_pioAddr addr); + u16(X86APIP inw) (X86EMU_pioAddr addr); + u32(X86APIP inl) (X86EMU_pioAddr addr); + void (X86APIP outb) (X86EMU_pioAddr addr, u8 val); + void (X86APIP outw) (X86EMU_pioAddr addr, u16 val); + void (X86APIP outl) (X86EMU_pioAddr addr, u32 val); +} X86EMU_pioFuncs; + +/**************************************************************************** +REMARKS: +Data structure containing ponters to memory access functions used by the +emulator. This is used so that the user program can hook all memory +access functions as necessary for the emulator. By default the emulator +contains simple functions that only access the internal memory of the +emulator. If you need specialised functions to handle access to different +types of memory (ie: hardware framebuffer accesses and BIOS memory access +etc), you will need to override this using the X86EMU_setupMemFuncs +function. + +HEADER: +x86emu.h + +MEMBERS: +rdb - Function to read a byte from an address +rdw - Function to read a word from an address +rdl - Function to read a dword from an address +wrb - Function to write a byte to an address +wrw - Function to write a word to an address +wrl - Function to write a dword to an address +****************************************************************************/ +typedef struct { + u8(X86APIP rdb) (u32 addr); + u16(X86APIP rdw) (u32 addr); + u32(X86APIP rdl) (u32 addr); + void (X86APIP wrb) (u32 addr, u8 val); + void (X86APIP wrw) (u32 addr, u16 val); + void (X86APIP wrl) (u32 addr, u32 val); +} X86EMU_memFuncs; + +/**************************************************************************** + Here are the default memory read and write + function in case they are needed as fallbacks. +***************************************************************************/ +extern u8 X86API rdb(u32 addr); +extern u16 X86API rdw(u32 addr); +extern u32 X86API rdl(u32 addr); +extern void X86API wrb(u32 addr, u8 val); +extern void X86API wrw(u32 addr, u16 val); +extern void X86API wrl(u32 addr, u32 val); + +#ifdef END_PACK +#pragma END_PACK +#endif + +/*--------------------- type definitions -----------------------------------*/ + +typedef void (X86APIP X86EMU_intrFuncs) (int num); +extern X86EMU_intrFuncs _X86EMU_intrTab[256]; + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + + void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs); + void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs); + void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]); + void X86EMU_prepareForInt(int num); + +/* decode.c */ + + void X86EMU_exec(void); + void X86EMU_halt_sys(void); + +#ifdef DEBUG +#define HALT_SYS() \ + printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \ + X86EMU_halt_sys() +#else +#define HALT_SYS() X86EMU_halt_sys() +#endif + +/* Debug options */ + +#define DEBUG_DECODE_F 0x000001 /* print decoded instruction */ +#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */ +#define DEBUG_STEP_F 0x000004 +#define DEBUG_DISASSEMBLE_F 0x000008 +#define DEBUG_BREAK_F 0x000010 +#define DEBUG_SVC_F 0x000020 +#define DEBUG_SAVE_IP_CS_F 0x000040 +#define DEBUG_FS_F 0x000080 +#define DEBUG_PROC_F 0x000100 +#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */ +#define DEBUG_TRACECALL_F 0x000400 +#define DEBUG_INSTRUMENT_F 0x000800 +#define DEBUG_MEM_TRACE_F 0x001000 +#define DEBUG_IO_TRACE_F 0x002000 +#define DEBUG_TRACECALL_REGS_F 0x004000 +#define DEBUG_DECODE_NOPRINT_F 0x008000 +#define DEBUG_EXIT 0x010000 +#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F) + + void X86EMU_trace_regs(void); + void X86EMU_trace_xregs(void); + void X86EMU_dump_memory(u16 seg, u16 off, u32 amt); + int X86EMU_trace_on(void); + int X86EMU_trace_off(void); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_X86EMU_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h new file mode 100644 index 0000000000..385b804dd7 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h @@ -0,0 +1,209 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for debug definitions. +* +****************************************************************************/ + +#ifndef __X86EMU_DEBUG_H +#define __X86EMU_DEBUG_H + +/*---------------------- Macros and type definitions ----------------------*/ + +/* checks to be enabled for "runtime" */ + +#define CHECK_IP_FETCH_F 0x1 +#define CHECK_SP_ACCESS_F 0x2 +#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */ +#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset */ + +#ifdef DEBUG +#define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F) +#define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F) +#define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F) +#define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F) +#else +#define CHECK_IP_FETCH() +#define CHECK_SP_ACCESS() +#define CHECK_MEM_ACCESS() +#define CHECK_DATA_ACCESS() +#endif + +#ifdef DEBUG +#define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F) +#define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F) +#define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F) +#define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F) +#define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F) +#define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F) +#define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F) +#define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_IP_CS_F) + +#define DEBUG_FS() (M.x86.debug & DEBUG_FS_F) +#define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F) +#define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F) +#define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F) +#define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F) +#define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F) +#define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F) +#define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F) +#define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F) +#else +#define DEBUG_INSTRUMENT() 0 +#define DEBUG_DECODE() 0 +#define DEBUG_TRACE() 0 +#define DEBUG_STEP() 0 +#define DEBUG_DISASSEMBLE() 0 +#define DEBUG_BREAK() 0 +#define DEBUG_SVC() 0 +#define DEBUG_SAVE_IP_CS() 0 +#define DEBUG_FS() 0 +#define DEBUG_PROC() 0 +#define DEBUG_SYSINT() 0 +#define DEBUG_TRACECALL() 0 +#define DEBUG_TRACECALLREGS() 0 +#define DEBUG_SYS() 0 +#define DEBUG_MEM_TRACE() 0 +#define DEBUG_IO_TRACE() 0 +#define DEBUG_DECODE_NOPRINT() 0 +#endif + +#ifdef DEBUG + +#define DECODE_PRINTF(x) if (DEBUG_DECODE()) \ + x86emu_decode_printf(x) +#define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \ + x86emu_decode_printf2(x,y) + +/* + * The following allow us to look at the bytes of an instruction. The + * first INCR_INSTRN_LEN, is called everytime bytes are consumed in + * the decoding process. The SAVE_IP_CS is called initially when the + * major opcode of the instruction is accessed. + */ +#define INC_DECODED_INST_LEN(x) \ + if (DEBUG_DECODE()) \ + x86emu_inc_decoded_inst_len(x) + +#define SAVE_IP_CS(x,y) \ + if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \ + | DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \ + M.x86.saved_cs = x; \ + M.x86.saved_ip = y; \ + } +#else +#define INC_DECODED_INST_LEN(x) +#define DECODE_PRINTF(x) +#define DECODE_PRINTF2(x,y) +#define SAVE_IP_CS(x,y) +#endif + +#ifdef DEBUG +#define TRACE_REGS() \ + if (DEBUG_DISASSEMBLE()) { \ + x86emu_just_disassemble(); \ + goto EndOfTheInstructionProcedure; \ + } \ + if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs() +#else +#define TRACE_REGS() +#endif + +#ifdef DEBUG +#define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step() +#else +#define SINGLE_STEP() +#endif + +#define TRACE_AND_STEP() \ + TRACE_REGS(); \ + SINGLE_STEP() + +#ifdef DEBUG +#define START_OF_INSTR() +#define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr(); +#define END_OF_INSTR_NO_TRACE() x86emu_end_instr(); +#else +#define START_OF_INSTR() +#define END_OF_INSTR() +#define END_OF_INSTR_NO_TRACE() +#endif + +#ifdef DEBUG +#define CALL_TRACE(u,v,w,x,s) \ + if (DEBUG_TRACECALLREGS()) \ + x86emu_dump_regs(); \ + if (DEBUG_TRACECALL()) \ + printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x); +#define RETURN_TRACE(n,u,v) \ + if (DEBUG_TRACECALLREGS()) \ + x86emu_dump_regs(); \ + if (DEBUG_TRACECALL()) \ + printk("%04x:%04x: %s\n",u,v,n); +#else +#define CALL_TRACE(u,v,w,x,s) +#define RETURN_TRACE(n,u,v) +#endif + +#ifdef DEBUG +#define DB(x) x +#else +#define DB(x) +#endif + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + + extern void x86emu_inc_decoded_inst_len(int x); + extern void x86emu_decode_printf(const char *x); + extern void x86emu_decode_printf2(const char *x, int y); + extern void x86emu_just_disassemble(void); + extern void x86emu_single_step(void); + extern void x86emu_end_instr(void); + extern void x86emu_dump_regs(void); + extern void x86emu_dump_xregs(void); + extern void x86emu_print_int_vect(u16 iv); + extern void x86emu_instrument_instruction(void); + extern void x86emu_check_ip_access(void); + extern void x86emu_check_sp_access(void); + extern void x86emu_check_mem_access(u32 p); + extern void x86emu_check_data_access(uint s, uint o); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_DEBUG_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h new file mode 100644 index 0000000000..49a1f7b540 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h @@ -0,0 +1,87 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for instruction decoding logic. +* +****************************************************************************/ + +#ifndef __X86EMU_DECODE_H +#define __X86EMU_DECODE_H + +/*---------------------- Macros and type definitions ----------------------*/ + +/* Instruction Decoding Stuff */ + +#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl) +#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r) +#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r) +#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r) +#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + + void x86emu_intr_raise(u8 type); + void fetch_decode_modrm(int *mod, int *regh, int *regl); + u8 fetch_byte_imm(void); + u16 fetch_word_imm(void); + u32 fetch_long_imm(void); + u8 fetch_data_byte(uint offset); + u8 fetch_data_byte_abs(uint segment, uint offset); + u16 fetch_data_word(uint offset); + u16 fetch_data_word_abs(uint segment, uint offset); + u32 fetch_data_long(uint offset); + u32 fetch_data_long_abs(uint segment, uint offset); + void store_data_byte(uint offset, u8 val); + void store_data_byte_abs(uint segment, uint offset, u8 val); + void store_data_word(uint offset, u16 val); + void store_data_word_abs(uint segment, uint offset, u16 val); + void store_data_long(uint offset, u32 val); + void store_data_long_abs(uint segment, uint offset, u32 val); + u8 *decode_rm_byte_register(int reg); + u16 *decode_rm_word_register(int reg); + u32 *decode_rm_long_register(int reg); + u16 *decode_rm_seg_register(int reg); + u32 decode_rm00_address(int rm); + u32 decode_rm01_address(int rm); + u32 decode_rm10_address(int rm); + u32 decode_sib_address(int sib, int mod); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_DECODE_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h new file mode 100644 index 0000000000..1c114987f0 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h @@ -0,0 +1,60 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for FPU instruction decoding. +* +****************************************************************************/ + +#ifndef __X86EMU_FPU_H +#define __X86EMU_FPU_H + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* these have to be defined, whether 8087 support compiled in or not. */ + + extern void x86emuOp_esc_coprocess_d8(u8 op1); + extern void x86emuOp_esc_coprocess_d9(u8 op1); + extern void x86emuOp_esc_coprocess_da(u8 op1); + extern void x86emuOp_esc_coprocess_db(u8 op1); + extern void x86emuOp_esc_coprocess_dc(u8 op1); + extern void x86emuOp_esc_coprocess_dd(u8 op1); + extern void x86emuOp_esc_coprocess_de(u8 op1); + extern void x86emuOp_esc_coprocess_df(u8 op1); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_FPU_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h new file mode 100644 index 0000000000..5a780e69c0 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h @@ -0,0 +1,119 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for FPU register definitions. +* +****************************************************************************/ + +#ifndef __X86EMU_FPU_REGS_H +#define __X86EMU_FPU_REGS_H + +#ifdef X86_FPU_SUPPORT + +#ifdef PACK +#pragma PACK +#endif + +/* Basic 8087 register can hold any of the following values: */ + +union x86_fpu_reg_u { + s8 tenbytes[10]; + double dval; + float fval; + s16 sval; + s32 lval; +}; + +struct x86_fpu_reg { + union x86_fpu_reg_u reg; + char tag; +}; + +/* + * Since we are not going to worry about the problems of aliasing + * registers, every time a register is modified, its result type is + * set in the tag fields for that register. If some operation + * attempts to access the type in a way inconsistent with its current + * storage format, then we flag the operation. If common, we'll + * attempt the conversion. + */ + +#define X86_FPU_VALID 0x80 +#define X86_FPU_REGTYP(r) ((r) & 0x7F) + +#define X86_FPU_WORD 0x0 +#define X86_FPU_SHORT 0x1 +#define X86_FPU_LONG 0x2 +#define X86_FPU_FLOAT 0x3 +#define X86_FPU_DOUBLE 0x4 +#define X86_FPU_LDBL 0x5 +#define X86_FPU_BSD 0x6 + +#define X86_FPU_STKTOP 0 + +struct x86_fpu_registers { + struct x86_fpu_reg x86_fpu_stack[8]; + int x86_fpu_flags; + int x86_fpu_config; /* rounding modes, etc. */ + short x86_fpu_tos, x86_fpu_bos; +}; + +#ifdef END_PACK +#pragma END_PACK +#endif + +/* + * There are two versions of the following macro. + * + * One version is for opcode D9, for which there are more than 32 + * instructions encoded in the second byte of the opcode. + * + * The other version, deals with all the other 7 i87 opcodes, for + * which there are only 32 strings needed to describe the + * instructions. + */ + +#endif /* X86_FPU_SUPPORT */ + +#ifdef DEBUG +#define DECODE_PRINTINSTR32(t,mod,rh,rl) \ + DECODE_PRINTF(t[(mod<<3)+(rh)]); +#define DECODE_PRINTINSTR256(t,mod,rh,rl) \ + DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]); +#else +#define DECODE_PRINTINSTR32(t,mod,rh,rl) +#define DECODE_PRINTINSTR256(t,mod,rh,rl) +#endif + +#endif /* __X86EMU_FPU_REGS_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h new file mode 100644 index 0000000000..1bc07a4e1d --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h @@ -0,0 +1,45 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for operand decoding functions. +* +****************************************************************************/ + +#ifndef __X86EMU_OPS_H +#define __X86EMU_OPS_H + +extern void (*x86emu_optab[0x100]) (u8 op1); +extern void (*x86emu_optab2[0x100]) (u8 op2); + +#endif /* __X86EMU_OPS_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h new file mode 100644 index 0000000000..aca132bf1c --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h @@ -0,0 +1,1053 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: Watcom C++ 10.6 or later +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Inline assembler versions of the primitive operand +* functions for faster performance. At the moment this is +* x86 inline assembler, but these functions could be replaced +* with native inline assembler for each supported processor +* platform. +* +****************************************************************************/ + +#ifndef __X86EMU_PRIM_ASM_H +#define __X86EMU_PRIM_ASM_H + +#ifdef __WATCOMC__ + +#ifndef VALIDATE +#define __HAVE_INLINE_ASSEMBLER__ +#endif + +u32 get_flags_asm(void); + +#pragma aux get_flags_asm = \ + "pushf" \ + "pop eax" \ + value [eax] \ + modify exact [eax]; + +u16 aaa_word_asm(u32 * flags, u16 d); + +#pragma aux aaa_word_asm = \ + "push [edi]" \ + "popf" \ + "aaa" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u16 aas_word_asm(u32 * flags, u16 d); + +#pragma aux aas_word_asm = \ + "push [edi]" \ + "popf" \ + "aas" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u16 aad_word_asm(u32 * flags, u16 d); + +#pragma aux aad_word_asm = \ + "push [edi]" \ + "popf" \ + "aad" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u16 aam_word_asm(u32 * flags, u8 d); + +#pragma aux aam_word_asm = \ + "push [edi]" \ + "popf" \ + "aam" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [ax] \ + modify exact [ax]; + +u8 adc_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux adc_byte_asm = \ + "push [edi]" \ + "popf" \ + "adc al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 adc_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux adc_word_asm = \ + "push [edi]" \ + "popf" \ + "adc ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 adc_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux adc_long_asm = \ + "push [edi]" \ + "popf" \ + "adc eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 add_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux add_byte_asm = \ + "push [edi]" \ + "popf" \ + "add al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 add_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux add_word_asm = \ + "push [edi]" \ + "popf" \ + "add ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 add_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux add_long_asm = \ + "push [edi]" \ + "popf" \ + "add eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 and_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux and_byte_asm = \ + "push [edi]" \ + "popf" \ + "and al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 and_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux and_word_asm = \ + "push [edi]" \ + "popf" \ + "and ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 and_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux and_long_asm = \ + "push [edi]" \ + "popf" \ + "and eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 cmp_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux cmp_byte_asm = \ + "push [edi]" \ + "popf" \ + "cmp al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 cmp_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux cmp_word_asm = \ + "push [edi]" \ + "popf" \ + "cmp ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 cmp_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux cmp_long_asm = \ + "push [edi]" \ + "popf" \ + "cmp eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 daa_byte_asm(u32 * flags, u8 d); + +#pragma aux daa_byte_asm = \ + "push [edi]" \ + "popf" \ + "daa" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u8 das_byte_asm(u32 * flags, u8 d); + +#pragma aux das_byte_asm = \ + "push [edi]" \ + "popf" \ + "das" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u8 dec_byte_asm(u32 * flags, u8 d); + +#pragma aux dec_byte_asm = \ + "push [edi]" \ + "popf" \ + "dec al" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u16 dec_word_asm(u32 * flags, u16 d); + +#pragma aux dec_word_asm = \ + "push [edi]" \ + "popf" \ + "dec ax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u32 dec_long_asm(u32 * flags, u32 d); + +#pragma aux dec_long_asm = \ + "push [edi]" \ + "popf" \ + "dec eax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] \ + value [eax] \ + modify exact [eax]; + +u8 inc_byte_asm(u32 * flags, u8 d); + +#pragma aux inc_byte_asm = \ + "push [edi]" \ + "popf" \ + "inc al" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u16 inc_word_asm(u32 * flags, u16 d); + +#pragma aux inc_word_asm = \ + "push [edi]" \ + "popf" \ + "inc ax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u32 inc_long_asm(u32 * flags, u32 d); + +#pragma aux inc_long_asm = \ + "push [edi]" \ + "popf" \ + "inc eax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] \ + value [eax] \ + modify exact [eax]; + +u8 or_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux or_byte_asm = \ + "push [edi]" \ + "popf" \ + "or al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 or_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux or_word_asm = \ + "push [edi]" \ + "popf" \ + "or ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 or_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux or_long_asm = \ + "push [edi]" \ + "popf" \ + "or eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 neg_byte_asm(u32 * flags, u8 d); + +#pragma aux neg_byte_asm = \ + "push [edi]" \ + "popf" \ + "neg al" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u16 neg_word_asm(u32 * flags, u16 d); + +#pragma aux neg_word_asm = \ + "push [edi]" \ + "popf" \ + "neg ax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u32 neg_long_asm(u32 * flags, u32 d); + +#pragma aux neg_long_asm = \ + "push [edi]" \ + "popf" \ + "neg eax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] \ + value [eax] \ + modify exact [eax]; + +u8 not_byte_asm(u32 * flags, u8 d); + +#pragma aux not_byte_asm = \ + "push [edi]" \ + "popf" \ + "not al" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] \ + value [al] \ + modify exact [al]; + +u16 not_word_asm(u32 * flags, u16 d); + +#pragma aux not_word_asm = \ + "push [edi]" \ + "popf" \ + "not ax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] \ + value [ax] \ + modify exact [ax]; + +u32 not_long_asm(u32 * flags, u32 d); + +#pragma aux not_long_asm = \ + "push [edi]" \ + "popf" \ + "not eax" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] \ + value [eax] \ + modify exact [eax]; + +u8 rcl_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux rcl_byte_asm = \ + "push [edi]" \ + "popf" \ + "rcl al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 rcl_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux rcl_word_asm = \ + "push [edi]" \ + "popf" \ + "rcl ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 rcl_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux rcl_long_asm = \ + "push [edi]" \ + "popf" \ + "rcl eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 rcr_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux rcr_byte_asm = \ + "push [edi]" \ + "popf" \ + "rcr al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 rcr_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux rcr_word_asm = \ + "push [edi]" \ + "popf" \ + "rcr ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 rcr_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux rcr_long_asm = \ + "push [edi]" \ + "popf" \ + "rcr eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 rol_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux rol_byte_asm = \ + "push [edi]" \ + "popf" \ + "rol al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 rol_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux rol_word_asm = \ + "push [edi]" \ + "popf" \ + "rol ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 rol_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux rol_long_asm = \ + "push [edi]" \ + "popf" \ + "rol eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 ror_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux ror_byte_asm = \ + "push [edi]" \ + "popf" \ + "ror al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 ror_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux ror_word_asm = \ + "push [edi]" \ + "popf" \ + "ror ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 ror_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux ror_long_asm = \ + "push [edi]" \ + "popf" \ + "ror eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 shl_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux shl_byte_asm = \ + "push [edi]" \ + "popf" \ + "shl al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 shl_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux shl_word_asm = \ + "push [edi]" \ + "popf" \ + "shl ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 shl_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux shl_long_asm = \ + "push [edi]" \ + "popf" \ + "shl eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 shr_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux shr_byte_asm = \ + "push [edi]" \ + "popf" \ + "shr al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 shr_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux shr_word_asm = \ + "push [edi]" \ + "popf" \ + "shr ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 shr_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux shr_long_asm = \ + "push [edi]" \ + "popf" \ + "shr eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u8 sar_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux sar_byte_asm = \ + "push [edi]" \ + "popf" \ + "sar al,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [cl] \ + value [al] \ + modify exact [al cl]; + +u16 sar_word_asm(u32 * flags, u16 d, u8 s); + +#pragma aux sar_word_asm = \ + "push [edi]" \ + "popf" \ + "sar ax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [cl] \ + value [ax] \ + modify exact [ax cl]; + +u32 sar_long_asm(u32 * flags, u32 d, u8 s); + +#pragma aux sar_long_asm = \ + "push [edi]" \ + "popf" \ + "sar eax,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [cl] \ + value [eax] \ + modify exact [eax cl]; + +u16 shld_word_asm(u32 * flags, u16 d, u16 fill, u8 s); + +#pragma aux shld_word_asm = \ + "push [edi]" \ + "popf" \ + "shld ax,dx,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [dx] [cl] \ + value [ax] \ + modify exact [ax dx cl]; + +u32 shld_long_asm(u32 * flags, u32 d, u32 fill, u8 s); + +#pragma aux shld_long_asm = \ + "push [edi]" \ + "popf" \ + "shld eax,edx,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [edx] [cl] \ + value [eax] \ + modify exact [eax edx cl]; + +u16 shrd_word_asm(u32 * flags, u16 d, u16 fill, u8 s); + +#pragma aux shrd_word_asm = \ + "push [edi]" \ + "popf" \ + "shrd ax,dx,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [dx] [cl] \ + value [ax] \ + modify exact [ax dx cl]; + +u32 shrd_long_asm(u32 * flags, u32 d, u32 fill, u8 s); + +#pragma aux shrd_long_asm = \ + "push [edi]" \ + "popf" \ + "shrd eax,edx,cl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [edx] [cl] \ + value [eax] \ + modify exact [eax edx cl]; + +u8 sbb_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux sbb_byte_asm = \ + "push [edi]" \ + "popf" \ + "sbb al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 sbb_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux sbb_word_asm = \ + "push [edi]" \ + "popf" \ + "sbb ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 sbb_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux sbb_long_asm = \ + "push [edi]" \ + "popf" \ + "sbb eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +u8 sub_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux sub_byte_asm = \ + "push [edi]" \ + "popf" \ + "sub al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 sub_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux sub_word_asm = \ + "push [edi]" \ + "popf" \ + "sub ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 sub_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux sub_long_asm = \ + "push [edi]" \ + "popf" \ + "sub eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +void test_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux test_byte_asm = \ + "push [edi]" \ + "popf" \ + "test al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + modify exact [al bl]; + +void test_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux test_word_asm = \ + "push [edi]" \ + "popf" \ + "test ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + modify exact [ax bx]; + +void test_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux test_long_asm = \ + "push [edi]" \ + "popf" \ + "test eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + modify exact [eax ebx]; + +u8 xor_byte_asm(u32 * flags, u8 d, u8 s); + +#pragma aux xor_byte_asm = \ + "push [edi]" \ + "popf" \ + "xor al,bl" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [al] [bl] \ + value [al] \ + modify exact [al bl]; + +u16 xor_word_asm(u32 * flags, u16 d, u16 s); + +#pragma aux xor_word_asm = \ + "push [edi]" \ + "popf" \ + "xor ax,bx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [ax] [bx] \ + value [ax] \ + modify exact [ax bx]; + +u32 xor_long_asm(u32 * flags, u32 d, u32 s); + +#pragma aux xor_long_asm = \ + "push [edi]" \ + "popf" \ + "xor eax,ebx" \ + "pushf" \ + "pop [edi]" \ + parm [edi] [eax] [ebx] \ + value [eax] \ + modify exact [eax ebx]; + +void imul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s); + +#pragma aux imul_byte_asm = \ + "push [edi]" \ + "popf" \ + "imul bl" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + parm [edi] [esi] [al] [bl] \ + modify exact [esi ax bl]; + +void imul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s); + +#pragma aux imul_word_asm = \ + "push [edi]" \ + "popf" \ + "imul bx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + "mov [ecx],dx" \ + parm [edi] [esi] [ecx] [ax] [bx]\ + modify exact [esi edi ax bx dx]; + +void imul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s); + +#pragma aux imul_long_asm = \ + "push [edi]" \ + "popf" \ + "imul ebx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],eax" \ + "mov [ecx],edx" \ + parm [edi] [esi] [ecx] [eax] [ebx] \ + modify exact [esi edi eax ebx edx]; + +void mul_byte_asm(u32 * flags, u16 * ax, u8 d, u8 s); + +#pragma aux mul_byte_asm = \ + "push [edi]" \ + "popf" \ + "mul bl" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + parm [edi] [esi] [al] [bl] \ + modify exact [esi ax bl]; + +void mul_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 d, u16 s); + +#pragma aux mul_word_asm = \ + "push [edi]" \ + "popf" \ + "mul bx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + "mov [ecx],dx" \ + parm [edi] [esi] [ecx] [ax] [bx]\ + modify exact [esi edi ax bx dx]; + +void mul_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 d, u32 s); + +#pragma aux mul_long_asm = \ + "push [edi]" \ + "popf" \ + "mul ebx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],eax" \ + "mov [ecx],edx" \ + parm [edi] [esi] [ecx] [eax] [ebx] \ + modify exact [esi edi eax ebx edx]; + +void idiv_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s); + +#pragma aux idiv_byte_asm = \ + "push [edi]" \ + "popf" \ + "idiv bl" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],al" \ + "mov [ecx],ah" \ + parm [edi] [esi] [ecx] [ax] [bl]\ + modify exact [esi edi ax bl]; + +void idiv_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s); + +#pragma aux idiv_word_asm = \ + "push [edi]" \ + "popf" \ + "idiv bx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + "mov [ecx],dx" \ + parm [edi] [esi] [ecx] [ax] [dx] [bx]\ + modify exact [esi edi ax dx bx]; + +void idiv_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s); + +#pragma aux idiv_long_asm = \ + "push [edi]" \ + "popf" \ + "idiv ebx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],eax" \ + "mov [ecx],edx" \ + parm [edi] [esi] [ecx] [eax] [edx] [ebx]\ + modify exact [esi edi eax edx ebx]; + +void div_byte_asm(u32 * flags, u8 * al, u8 * ah, u16 d, u8 s); + +#pragma aux div_byte_asm = \ + "push [edi]" \ + "popf" \ + "div bl" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],al" \ + "mov [ecx],ah" \ + parm [edi] [esi] [ecx] [ax] [bl]\ + modify exact [esi edi ax bl]; + +void div_word_asm(u32 * flags, u16 * ax, u16 * dx, u16 dlo, u16 dhi, u16 s); + +#pragma aux div_word_asm = \ + "push [edi]" \ + "popf" \ + "div bx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],ax" \ + "mov [ecx],dx" \ + parm [edi] [esi] [ecx] [ax] [dx] [bx]\ + modify exact [esi edi ax dx bx]; + +void div_long_asm(u32 * flags, u32 * eax, u32 * edx, u32 dlo, u32 dhi, u32 s); + +#pragma aux div_long_asm = \ + "push [edi]" \ + "popf" \ + "div ebx" \ + "pushf" \ + "pop [edi]" \ + "mov [esi],eax" \ + "mov [ecx],edx" \ + parm [edi] [esi] [ecx] [eax] [edx] [ebx]\ + modify exact [esi edi eax edx ebx]; + +#endif + +#endif /* __X86EMU_PRIM_ASM_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h new file mode 100644 index 0000000000..0f0e78d717 --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h @@ -0,0 +1,141 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for primitive operation functions. +* +****************************************************************************/ + +#ifndef __X86EMU_PRIM_OPS_H +#define __X86EMU_PRIM_OPS_H + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + + u16 aaa_word(u16 d); + u16 aas_word(u16 d); + u16 aad_word(u16 d); + u16 aam_word(u8 d); + u8 adc_byte(u8 d, u8 s); + u16 adc_word(u16 d, u16 s); + u32 adc_long(u32 d, u32 s); + u8 add_byte(u8 d, u8 s); + u16 add_word(u16 d, u16 s); + u32 add_long(u32 d, u32 s); + u8 and_byte(u8 d, u8 s); + u16 and_word(u16 d, u16 s); + u32 and_long(u32 d, u32 s); + u8 cmp_byte(u8 d, u8 s); + u16 cmp_word(u16 d, u16 s); + u32 cmp_long(u32 d, u32 s); + u8 daa_byte(u8 d); + u8 das_byte(u8 d); + u8 dec_byte(u8 d); + u16 dec_word(u16 d); + u32 dec_long(u32 d); + u8 inc_byte(u8 d); + u16 inc_word(u16 d); + u32 inc_long(u32 d); + u8 or_byte(u8 d, u8 s); + u16 or_word(u16 d, u16 s); + u32 or_long(u32 d, u32 s); + u8 neg_byte(u8 s); + u16 neg_word(u16 s); + u32 neg_long(u32 s); + u8 not_byte(u8 s); + u16 not_word(u16 s); + u32 not_long(u32 s); + u8 rcl_byte(u8 d, u8 s); + u16 rcl_word(u16 d, u8 s); + u32 rcl_long(u32 d, u8 s); + u8 rcr_byte(u8 d, u8 s); + u16 rcr_word(u16 d, u8 s); + u32 rcr_long(u32 d, u8 s); + u8 rol_byte(u8 d, u8 s); + u16 rol_word(u16 d, u8 s); + u32 rol_long(u32 d, u8 s); + u8 ror_byte(u8 d, u8 s); + u16 ror_word(u16 d, u8 s); + u32 ror_long(u32 d, u8 s); + u8 shl_byte(u8 d, u8 s); + u16 shl_word(u16 d, u8 s); + u32 shl_long(u32 d, u8 s); + u8 shr_byte(u8 d, u8 s); + u16 shr_word(u16 d, u8 s); + u32 shr_long(u32 d, u8 s); + u8 sar_byte(u8 d, u8 s); + u16 sar_word(u16 d, u8 s); + u32 sar_long(u32 d, u8 s); + u16 shld_word(u16 d, u16 fill, u8 s); + u32 shld_long(u32 d, u32 fill, u8 s); + u16 shrd_word(u16 d, u16 fill, u8 s); + u32 shrd_long(u32 d, u32 fill, u8 s); + u8 sbb_byte(u8 d, u8 s); + u16 sbb_word(u16 d, u16 s); + u32 sbb_long(u32 d, u32 s); + u8 sub_byte(u8 d, u8 s); + u16 sub_word(u16 d, u16 s); + u32 sub_long(u32 d, u32 s); + void test_byte(u8 d, u8 s); + void test_word(u16 d, u16 s); + void test_long(u32 d, u32 s); + u8 xor_byte(u8 d, u8 s); + u16 xor_word(u16 d, u16 s); + u32 xor_long(u32 d, u32 s); + void imul_byte(u8 s); + void imul_word(u16 s); + void imul_long(u32 s); + void imul_long_direct(u32 * res_lo, u32 * res_hi, u32 d, u32 s); + void mul_byte(u8 s); + void mul_word(u16 s); + void mul_long(u32 s); + void idiv_byte(u8 s); + void idiv_word(u16 s); + void idiv_long(u32 s); + void div_byte(u8 s); + void div_word(u16 s); + void div_long(u32 s); + void ins(int size); + void outs(int size); + u16 mem_access_word(int addr); + void push_word(u16 w); + void push_long(u32 w); + u16 pop_word(void); + u32 pop_long(void); + void cpuid(void); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_PRIM_OPS_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h new file mode 100644 index 0000000000..646ec9defe --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h @@ -0,0 +1,77 @@ +/**************************************************************************** +* +* Inline helpers for x86emu +* +* Copyright (C) 2008 Bart Trojanowski, Symbio Technologies, LLC +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: GNU C +* Environment: GCC on i386 or x86-64 +* Developer: Bart Trojanowski +* +* Description: This file defines a few x86 macros that can be used by the +* emulator to execute native instructions. +* +* For PIC vs non-PIC code refer to: +* http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well +* +****************************************************************************/ +#ifndef __X86EMU_PRIM_X86_GCC_H +#define __X86EMU_PRIM_X86_GCC_H + +#include "x86emu/types.h" + +#if !defined(__GNUC__) || !(defined (__i386__) || defined(__i386) || defined(__AMD64__) || defined(__amd64__)) +#error This file is intended to be used by gcc on i386 or x86-64 system +#endif + +#if defined(__PIC__) && defined(__i386__) + +#define X86EMU_HAS_HW_CPUID 1 +static inline void +hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d) +{ + __asm__ __volatile__("pushl %%ebx \n\t" + "cpuid \n\t" + "movl %%ebx, %1 \n\t" + "popl %%ebx \n\t":"=a"(*a), "=r"(*b), + "=c"(*c), "=d"(*d) + :"a"(*a), "c"(*c) + :"cc"); +} + +#else /* ! (__PIC__ && __i386__) */ + +#define x86EMU_HAS_HW_CPUID 1 +static inline void +hw_cpuid(u32 * a, u32 * b, u32 * c, u32 * d) +{ + __asm__ __volatile__("cpuid":"=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) + :"a"(*a), "c"(*c) + :"cc"); +} + +#endif /* __PIC__ && __i386__ */ + +#endif /* __X86EMU_PRIM_X86_GCC_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h new file mode 100644 index 0000000000..203a442adc --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h @@ -0,0 +1,342 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for x86 register definitions. +* +****************************************************************************/ + +#ifndef __X86EMU_REGS_H +#define __X86EMU_REGS_H + +/*---------------------- Macros and type definitions ----------------------*/ + +#ifdef PACK +#pragma PACK +#endif + +/* + * General EAX, EBX, ECX, EDX type registers. Note that for + * portability, and speed, the issue of byte swapping is not addressed + * in the registers. All registers are stored in the default format + * available on the host machine. The only critical issue is that the + * registers should line up EXACTLY in the same manner as they do in + * the 386. That is: + * + * EAX & 0xff === AL + * EAX & 0xffff == AX + * + * etc. The result is that alot of the calculations can then be + * done using the native instruction set fully. + */ + +#ifdef __BIG_ENDIAN__ + +typedef struct { + u32 e_reg; +} I32_reg_t; + +typedef struct { + u16 filler0, x_reg; +} I16_reg_t; + +typedef struct { + u8 filler0, filler1, h_reg, l_reg; +} I8_reg_t; + +#else /* !__BIG_ENDIAN__ */ + +typedef struct { + u32 e_reg; +} I32_reg_t; + +typedef struct { + u16 x_reg; +} I16_reg_t; + +typedef struct { + u8 l_reg, h_reg; +} I8_reg_t; + +#endif /* BIG_ENDIAN */ + +typedef union { + I32_reg_t I32_reg; + I16_reg_t I16_reg; + I8_reg_t I8_reg; +} i386_general_register; + +struct i386_general_regs { + i386_general_register A, B, C, D; +}; + +typedef struct i386_general_regs Gen_reg_t; + +struct i386_special_regs { + i386_general_register SP, BP, SI, DI, IP; + u32 FLAGS; +}; + +/* + * Segment registers here represent the 16 bit quantities + * CS, DS, ES, SS. + */ + +struct i386_segment_regs { + u16 CS, DS, SS, ES, FS, GS; +}; + +/* 8 bit registers */ +#define R_AH gen.A.I8_reg.h_reg +#define R_AL gen.A.I8_reg.l_reg +#define R_BH gen.B.I8_reg.h_reg +#define R_BL gen.B.I8_reg.l_reg +#define R_CH gen.C.I8_reg.h_reg +#define R_CL gen.C.I8_reg.l_reg +#define R_DH gen.D.I8_reg.h_reg +#define R_DL gen.D.I8_reg.l_reg + +/* 16 bit registers */ +#define R_AX gen.A.I16_reg.x_reg +#define R_BX gen.B.I16_reg.x_reg +#define R_CX gen.C.I16_reg.x_reg +#define R_DX gen.D.I16_reg.x_reg + +/* 32 bit extended registers */ +#define R_EAX gen.A.I32_reg.e_reg +#define R_EBX gen.B.I32_reg.e_reg +#define R_ECX gen.C.I32_reg.e_reg +#define R_EDX gen.D.I32_reg.e_reg + +/* special registers */ +#define R_SP spc.SP.I16_reg.x_reg +#define R_BP spc.BP.I16_reg.x_reg +#define R_SI spc.SI.I16_reg.x_reg +#define R_DI spc.DI.I16_reg.x_reg +#define R_IP spc.IP.I16_reg.x_reg +#define R_FLG spc.FLAGS + +/* special registers */ +#define R_SP spc.SP.I16_reg.x_reg +#define R_BP spc.BP.I16_reg.x_reg +#define R_SI spc.SI.I16_reg.x_reg +#define R_DI spc.DI.I16_reg.x_reg +#define R_IP spc.IP.I16_reg.x_reg +#define R_FLG spc.FLAGS + +/* special registers */ +#define R_ESP spc.SP.I32_reg.e_reg +#define R_EBP spc.BP.I32_reg.e_reg +#define R_ESI spc.SI.I32_reg.e_reg +#define R_EDI spc.DI.I32_reg.e_reg +#define R_EIP spc.IP.I32_reg.e_reg +#define R_EFLG spc.FLAGS + +/* segment registers */ +#define R_CS seg.CS +#define R_DS seg.DS +#define R_SS seg.SS +#define R_ES seg.ES +#define R_FS seg.FS +#define R_GS seg.GS + +/* flag conditions */ +#define FB_CF 0x0001 /* CARRY flag */ +#define FB_PF 0x0004 /* PARITY flag */ +#define FB_AF 0x0010 /* AUX flag */ +#define FB_ZF 0x0040 /* ZERO flag */ +#define FB_SF 0x0080 /* SIGN flag */ +#define FB_TF 0x0100 /* TRAP flag */ +#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ +#define FB_DF 0x0400 /* DIR flag */ +#define FB_OF 0x0800 /* OVERFLOW flag */ + +/* 80286 and above always have bit#1 set */ +#define F_ALWAYS_ON (0x0002) /* flag bits always on */ + +/* + * Define a mask for only those flag bits we will ever pass back + * (via PUSHF) + */ +#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) + +/* following bits masked in to a 16bit quantity */ + +#define F_CF 0x0001 /* CARRY flag */ +#define F_PF 0x0004 /* PARITY flag */ +#define F_AF 0x0010 /* AUX flag */ +#define F_ZF 0x0040 /* ZERO flag */ +#define F_SF 0x0080 /* SIGN flag */ +#define F_TF 0x0100 /* TRAP flag */ +#define F_IF 0x0200 /* INTERRUPT ENABLE flag */ +#define F_DF 0x0400 /* DIR flag */ +#define F_OF 0x0800 /* OVERFLOW flag */ + +#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag)) +#define SET_FLAG(flag) (M.x86.R_FLG |= (flag)) +#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag)) +#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag)) +#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0) + +#define CONDITIONAL_SET_FLAG(COND,FLAG) \ + if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) + +#define F_PF_CALC 0x010000 /* PARITY flag has been calced */ +#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */ +#define F_SF_CALC 0x040000 /* SIGN flag has been calced */ + +#define F_ALL_CALC 0xff0000 /* All have been calced */ + +/* + * Emulator machine state. + * Segment usage control. + */ +#define SYSMODE_SEG_DS_SS 0x00000001 +#define SYSMODE_SEGOVR_CS 0x00000002 +#define SYSMODE_SEGOVR_DS 0x00000004 +#define SYSMODE_SEGOVR_ES 0x00000008 +#define SYSMODE_SEGOVR_FS 0x00000010 +#define SYSMODE_SEGOVR_GS 0x00000020 +#define SYSMODE_SEGOVR_SS 0x00000040 +#define SYSMODE_PREFIX_REPE 0x00000080 +#define SYSMODE_PREFIX_REPNE 0x00000100 +#define SYSMODE_PREFIX_DATA 0x00000200 +#define SYSMODE_PREFIX_ADDR 0x00000400 +#define SYSMODE_INTR_PENDING 0x10000000 +#define SYSMODE_EXTRN_INTR 0x20000000 +#define SYSMODE_HALTED 0x40000000 + +#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \ + SYSMODE_SEGOVR_CS | \ + SYSMODE_SEGOVR_DS | \ + SYSMODE_SEGOVR_ES | \ + SYSMODE_SEGOVR_FS | \ + SYSMODE_SEGOVR_GS | \ + SYSMODE_SEGOVR_SS) +#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \ + SYSMODE_SEGOVR_CS | \ + SYSMODE_SEGOVR_DS | \ + SYSMODE_SEGOVR_ES | \ + SYSMODE_SEGOVR_FS | \ + SYSMODE_SEGOVR_GS | \ + SYSMODE_SEGOVR_SS | \ + SYSMODE_PREFIX_DATA | \ + SYSMODE_PREFIX_ADDR) + +#define INTR_SYNCH 0x1 +#define INTR_ASYNCH 0x2 +#define INTR_HALTED 0x4 + +typedef struct { + struct i386_general_regs gen; + struct i386_special_regs spc; + struct i386_segment_regs seg; + /* + * MODE contains information on: + * REPE prefix 2 bits repe,repne + * SEGMENT overrides 5 bits normal,DS,SS,CS,ES + * Delayed flag set 3 bits (zero, signed, parity) + * reserved 6 bits + * interrupt # 8 bits instruction raised interrupt + * BIOS video segregs 4 bits + * Interrupt Pending 1 bits + * Extern interrupt 1 bits + * Halted 1 bits + */ + u32 mode; + volatile int intr; /* mask of pending interrupts */ + int debug; +#ifdef DEBUG + int check; + u16 saved_ip; + u16 saved_cs; + int enc_pos; + int enc_str_pos; + char decode_buf[32]; /* encoded byte stream */ + char decoded_buf[256]; /* disassembled strings */ +#endif + u8 intno; + u8 __pad[3]; +} X86EMU_regs; + +/**************************************************************************** +REMARKS: +Structure maintaining the emulator machine state. + +MEMBERS: +mem_base - Base real mode memory for the emulator +mem_size - Size of the real mode memory block for the emulator +private - private data pointer +x86 - X86 registers +****************************************************************************/ +typedef struct { + unsigned long mem_base; + unsigned long mem_size; +#ifdef __cplusplus + void *_private; +#else + void *private; +#endif + X86EMU_regs x86; +} X86EMU_sysEnv; + +#ifdef END_PACK +#pragma END_PACK +#endif + +/*----------------------------- Global Variables --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Global emulator machine state. + * + * We keep it global to avoid pointer dereferences in the code for speed. + */ + + extern X86EMU_sysEnv _X86EMU_env; +#define M _X86EMU_env + +/*-------------------------- Function Prototypes --------------------------*/ + +/* Function to log information at runtime */ + +#include +#define printk(fmt...) dprintf(fmt) +// void printk(const char *fmt, ...); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_REGS_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h new file mode 100644 index 0000000000..5a6ef01f8b --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h @@ -0,0 +1,80 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for x86 emulator type definitions. +* +****************************************************************************/ + +#ifndef __X86EMU_TYPES_H +#define __X86EMU_TYPES_H + +#ifndef NO_SYS_HEADERS +#include +#endif + +/* + * The following kludge is an attempt to work around typedef conflicts with + * . + */ +#define u8 x86emuu8 +#define u16 x86emuu16 +#define u32 x86emuu32 +#define u64 x86emuu64 +#define s8 x86emus8 +#define s16 x86emus16 +#define s32 x86emus32 +#define s64 x86emus64 +#define uint x86emuuint +#define sint x86emusint + +/*---------------------- Macros and type definitions ----------------------*/ + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; + +typedef unsigned int uint; +typedef int sint; + +typedef u16 X86EMU_pioAddr; + +#endif /* __X86EMU_TYPES_H */ diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h b/src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h new file mode 100644 index 0000000000..f11dc102ff --- /dev/null +++ b/src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h @@ -0,0 +1,100 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for system specific functions. These functions +* are always compiled and linked in the OS depedent libraries, +* and never in a binary portable driver. +* +****************************************************************************/ + +#ifndef __X86EMU_X86EMUI_H +#define __X86EMU_X86EMUI_H + +/* If we are compiling in C++ mode, we can compile some functions as + * inline to increase performance (however the code size increases quite + * dramatically in this case). + */ + +#if defined(__cplusplus) && !defined(_NO_INLINE) +#define _INLINE inline +#else +#define _INLINE static +#endif + +/* Get rid of unused parameters in C++ compilation mode */ + +#ifdef __cplusplus +#define X86EMU_UNUSED(v) +#else +#define X86EMU_UNUSED(v) v +#endif + +#include "x86emu.h" +#include "x86emu/regs.h" +#include "x86emu/debug.h" +#include "x86emu/decode.h" +#include "x86emu/ops.h" +#include "x86emu/prim_ops.h" +#include "x86emu/fpu.h" +#include "x86emu/fpu_regs.h" + +#ifndef NO_SYS_HEADERS +#include +#include +#include +#endif +/*--------------------------- Inline Functions ----------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + + extern u8(X86APIP sys_rdb) (u32 addr); + extern u16(X86APIP sys_rdw) (u32 addr); + extern u32(X86APIP sys_rdl) (u32 addr); + extern void (X86APIP sys_wrb) (u32 addr, u8 val); + extern void (X86APIP sys_wrw) (u32 addr, u16 val); + extern void (X86APIP sys_wrl) (u32 addr, u32 val); + + extern u8(X86APIP sys_inb) (X86EMU_pioAddr addr); + extern u16(X86APIP sys_inw) (X86EMU_pioAddr addr); + extern u32(X86APIP sys_inl) (X86EMU_pioAddr addr); + extern void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val); + extern void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val); + extern void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif +#endif /* __X86EMU_X86EMUI_H */ From b28f734b1cd385194683bccf9f5c46a16a7644e7 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 3 Aug 2012 16:18:49 +0100 Subject: [PATCH 158/273] Remove line copied from old vm86 code that shouldn't be there. --- src/add-ons/kernel/generic/bios/bios.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/add-ons/kernel/generic/bios/bios.cpp b/src/add-ons/kernel/generic/bios/bios.cpp index 8ae2745852..a887896226 100644 --- a/src/add-ons/kernel/generic/bios/bios.cpp +++ b/src/add-ons/kernel/generic/bios/bios.cpp @@ -235,7 +235,6 @@ bios_prepare(bios_state** _state) (void*)state->mapped_address, kTotalSize); return status; } - *((uint32 *)state->mapped_address) = 0xdeadbeef; // Map the extended BIOS data area and VGA memory. void* address = (void*)(state->mapped_address + kEBDABase); From 9f90e8a9649d7b63607e2d90f94717bed2b072b5 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 3 Aug 2012 16:28:20 +0100 Subject: [PATCH 159/273] Updated drivers to use BIOS module instead of vm86. --- .../kernel/drivers/graphics/3dfx/driver.cpp | 1 - .../kernel/drivers/graphics/ati/driver.cpp | 108 ++++--- .../drivers/graphics/intel_810/driver.cpp | 72 +++-- .../kernel/drivers/graphics/s3/driver.cpp | 75 +++-- .../kernel/drivers/graphics/vesa/vesa.cpp | 288 ++++++++++-------- 5 files changed, 313 insertions(+), 231 deletions(-) diff --git a/src/add-ons/kernel/drivers/graphics/3dfx/driver.cpp b/src/add-ons/kernel/drivers/graphics/3dfx/driver.cpp index 4bf33b7ffe..70ca7220bf 100644 --- a/src/add-ons/kernel/drivers/graphics/3dfx/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/3dfx/driver.cpp @@ -14,7 +14,6 @@ #include #ifdef __HAIKU__ #include -#include #endif // __HAIKU__ #include "DriverInterface.h" diff --git a/src/add-ons/kernel/drivers/graphics/ati/driver.cpp b/src/add-ons/kernel/drivers/graphics/ati/driver.cpp index b8eca53943..cc302c6b04 100644 --- a/src/add-ons/kernel/drivers/graphics/ati/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/ati/driver.cpp @@ -8,12 +8,12 @@ #include #include +#include #include #include #include #include #include -#include #include "DriverInterface.h" @@ -249,52 +249,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw) #define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4) #define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf) - vm86_state vmState; - - status_t status = vm86_prepare(&vmState, 0x2000); + bios_module_info* biosModule; + status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule); if (status != B_OK) { - TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n", + TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n", status); return status; } - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 0; // 0 = report DDC service - vmState.regs.ecx = 0; - vmState.regs.es = 0; - vmState.regs.edi = 0; + bios_state* state; + status = biosModule->prepare(&state); + if (status != B_OK) { + TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n", + status); + put_module(B_BIOS_MODULE_NAME); + return status; + } - status = vm86_do_int(&vmState, 0x10); + bios_regs regs = {}; + regs.eax = 0x4f15; + regs.ebx = 0; // 0 = report DDC service + regs.ecx = 0; + regs.es = 0; + regs.edi = 0; + + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { // AH contains the error code, and AL determines whether or not the // function is supported. - if (vmState.regs.eax != 0x4f) + if (regs.eax != 0x4f) status = B_NOT_SUPPORTED; // Test if DDC is supported by the monitor. - if ((vmState.regs.ebx & 3) == 0) + if ((regs.ebx & 3) == 0) status = B_NOT_SUPPORTED; } if (status == B_OK) { - // According to the author of the vm86 functions, the address of any - // object to receive data must be >= 0x1000 and within the ram size - // specified in the second argument of the vm86_prepare() call above. - // Thus, the address of the struct to receive the EDID info is set to - // 0x1000. + edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state, + sizeof(edid1_raw)); + if (edid == NULL) { + status = B_NO_MEMORY; + goto out; + } - edid1_raw* edid = (edid1_raw*)0x1000; + regs.eax = 0x4f15; + regs.ebx = 1; // 1 = read EDID + regs.ecx = 0; + regs.edx = 0; + regs.es = ADDRESS_SEGMENT(edid); + regs.edi = ADDRESS_OFFSET(edid); - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 1; // 1 = read EDID - vmState.regs.ecx = 0; - vmState.regs.edx = 0; - vmState.regs.es = ADDRESS_SEGMENT(edid); - vmState.regs.edi = ADDRESS_OFFSET(edid); - - status = vm86_do_int(&vmState, 0x10); + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { - if (vmState.regs.eax != 0x4f) { + if (regs.eax != 0x4f) { status = B_NOT_SUPPORTED; } else { // Copy the EDID info to the caller's location, and compute the @@ -322,8 +330,9 @@ GetEdidFromBIOS(edid1_raw& edidRaw) } } - vm86_cleanup(&vmState); - +out: + biosModule->finish(state); + put_module(B_BIOS_MODULE_NAME); return status; } @@ -336,31 +345,40 @@ SetVesaDisplayMode(uint16 mode) #define SET_MODE_MASK 0x01ff #define SET_MODE_LINEAR_BUFFER (1 << 14) - vm86_state vmState; - - status_t status = vm86_prepare(&vmState, 0x2000); + bios_module_info* biosModule; + status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule); if (status != B_OK) { - TRACE("SetVesaDisplayMode(); vm86_prepare() failed, status: 0x%lx\n", - status); + TRACE("SetVesaDisplayMode(0x%x): failed to get BIOS module: 0x%" B_PRIx32 + "\n", mode, status); return status; } - vmState.regs.eax = 0x4f02; - vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER; - - status = vm86_do_int(&vmState, 0x10); + bios_state* state; + status = biosModule->prepare(&state); if (status != B_OK) { - TRACE("SetVesaDisplayMode(0x%x): vm86_do_int failed\n", mode); + TRACE("SetVesaDisplayMode(0x%x): bios_prepare() failed: 0x%" B_PRIx32 + "\n", mode, status); + put_module(B_BIOS_MODULE_NAME); + return status; } - if (status == B_OK && (vmState.regs.eax & 0xffff) != 0x4f) { - TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04lx\n", mode, - vmState.regs.eax & 0xffff); + bios_regs regs = {}; + regs.eax = 0x4f02; + regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER; + + status = biosModule->interrupt(state, 0x10, ®s); + if (status != B_OK) { + TRACE("SetVesaDisplayMode(0x%x): BIOS interrupt failed\n", mode); + } + + if (status == B_OK && (regs.eax & 0xffff) != 0x4f) { + TRACE("SetVesaDisplayMode(0x%x): BIOS returned 0x%04" B_PRIx32 "\n", + mode, regs.eax & 0xffff); status = B_ERROR; } - vm86_cleanup(&vmState); - + biosModule->finish(state); + put_module(B_BIOS_MODULE_NAME); return status; } diff --git a/src/add-ons/kernel/drivers/graphics/intel_810/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_810/driver.cpp index eddd81d017..edb7b9e46a 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_810/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_810/driver.cpp @@ -10,12 +10,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include "DriverInterface.h" @@ -148,52 +148,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw) #define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4) #define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf) - vm86_state vmState; - - status_t status = vm86_prepare(&vmState, 0x2000); + bios_module_info* biosModule; + status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule); if (status != B_OK) { - TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n", + TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n", status); return status; } - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 0; // 0 = report DDC service - vmState.regs.ecx = 0; - vmState.regs.es = 0; - vmState.regs.edi = 0; + bios_state* state; + status = biosModule->prepare(&state); + if (status != B_OK) { + TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n", + status); + put_module(B_BIOS_MODULE_NAME); + return status; + } - status = vm86_do_int(&vmState, 0x10); + bios_regs regs = {}; + regs.eax = 0x4f15; + regs.ebx = 0; // 0 = report DDC service + regs.ecx = 0; + regs.es = 0; + regs.edi = 0; + + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { - // AH contains the error code, and AL determines wether or not the + // AH contains the error code, and AL determines whether or not the // function is supported. - if (vmState.regs.eax != 0x4f) + if (regs.eax != 0x4f) status = B_NOT_SUPPORTED; // Test if DDC is supported by the monitor. - if ((vmState.regs.ebx & 3) == 0) + if ((regs.ebx & 3) == 0) status = B_NOT_SUPPORTED; } if (status == B_OK) { - // According to the author of the vm86 functions, the address of any - // object to receive data must be >= 0x1000 and within the ram size - // specified in the second argument of the vm86_prepare() call above. - // Thus, the address of the struct to receive the EDID info is set to - // 0x1000. + edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state, + sizeof(edid1_raw)); + if (edid == NULL) { + status = B_NO_MEMORY; + goto out; + } - edid1_raw* edid = (edid1_raw*)0x1000; + regs.eax = 0x4f15; + regs.ebx = 1; // 1 = read EDID + regs.ecx = 0; + regs.edx = 0; + regs.es = ADDRESS_SEGMENT(edid); + regs.edi = ADDRESS_OFFSET(edid); - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 1; // 1 = read EDID - vmState.regs.ecx = 0; - vmState.regs.edx = 0; - vmState.regs.es = ADDRESS_SEGMENT(edid); - vmState.regs.edi = ADDRESS_OFFSET(edid); - - status = vm86_do_int(&vmState, 0x10); + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { - if (vmState.regs.eax != 0x4f) { + if (regs.eax != 0x4f) { status = B_NOT_SUPPORTED; } else { // Copy the EDID info to the caller's location, and compute the @@ -221,9 +229,11 @@ GetEdidFromBIOS(edid1_raw& edidRaw) } } - vm86_cleanup(&vmState); +out: + biosModule->finish(state); + put_module(B_BIOS_MODULE_NAME); - TRACE("GetEdidFromBIOS() status: 0x%lx\n", status); + TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status); return status; } diff --git a/src/add-ons/kernel/drivers/graphics/s3/driver.cpp b/src/add-ons/kernel/drivers/graphics/s3/driver.cpp index d57d8947e7..d737fdef63 100644 --- a/src/add-ons/kernel/drivers/graphics/s3/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/s3/driver.cpp @@ -8,13 +8,13 @@ #include #include +#ifdef __HAIKU__ +#include +#endif // __HAIKU__ #include #include #include #include -#ifdef __HAIKU__ -#include -#endif // __HAIKU__ #include "DriverInterface.h" @@ -493,51 +493,60 @@ GetEdidFromBIOS(edid1_raw& edidRaw) #define ADDRESS_SEGMENT(address) ((addr_t)(address) >> 4) #define ADDRESS_OFFSET(address) ((addr_t)(address) & 0xf) - vm86_state vmState; - - status_t status = vm86_prepare(&vmState, 0x2000); + bios_module_info* biosModule; + status_t status = get_module(B_BIOS_MODULE_NAME, (module_info**)&biosModule); if (status != B_OK) { - TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: %lx\n", status); + TRACE("GetEdidFromBIOS(): failed to get BIOS module: 0x%" B_PRIx32 "\n", + status); return status; } - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 0; // 0 = report DDC service - vmState.regs.ecx = 0; - vmState.regs.es = 0; - vmState.regs.edi = 0; + bios_state* state; + status = biosModule->prepare(&state); + if (status != B_OK) { + TRACE("GetEdidFromBIOS(): bios_prepare() failed: 0x%" B_PRIx32 "\n", + status); + put_module(B_BIOS_MODULE_NAME); + return status; + } - status = vm86_do_int(&vmState, 0x10); + bios_regs regs = {}; + regs.eax = 0x4f15; + regs.ebx = 0; // 0 = report DDC service + regs.ecx = 0; + regs.es = 0; + regs.edi = 0; + + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { // AH contains the error code, and AL determines whether or not the // function is supported. - if (vmState.regs.eax != 0x4f) + if (regs.eax != 0x4f) status = B_NOT_SUPPORTED; // Test if DDC is supported by the monitor. - if ((vmState.regs.ebx & 3) == 0) + if ((regs.ebx & 3) == 0) status = B_NOT_SUPPORTED; } if (status == B_OK) { - // According to the author of the vm86 functions, the address of any - // object to receive data must be >= 0x1000 and within the ram size - // specified in the second argument of the vm86_prepare() call above. - // Thus, the address of the struct to receive the EDID info is set to - // 0x1000. + edid1_raw* edid = (edid1_raw*)biosModule->allocate_mem(state, + sizeof(edid1_raw)); + if (edid == NULL) { + status = B_NO_MEMORY; + goto out; + } - edid1_raw* edid = (edid1_raw*)0x1000; + regs.eax = 0x4f15; + regs.ebx = 1; // 1 = read EDID + regs.ecx = 0; + regs.edx = 0; + regs.es = ADDRESS_SEGMENT(edid); + regs.edi = ADDRESS_OFFSET(edid); - vmState.regs.eax = 0x4f15; - vmState.regs.ebx = 1; // 1 = read EDID - vmState.regs.ecx = 0; - vmState.regs.edx = 0; - vmState.regs.es = ADDRESS_SEGMENT(edid); - vmState.regs.edi = ADDRESS_OFFSET(edid); - - status = vm86_do_int(&vmState, 0x10); + status = biosModule->interrupt(state, 0x10, ®s); if (status == B_OK) { - if (vmState.regs.eax != 0x4f) { + if (regs.eax != 0x4f) { status = B_NOT_SUPPORTED; } else { // Copy the EDID info to the caller's location, and compute the @@ -565,9 +574,11 @@ GetEdidFromBIOS(edid1_raw& edidRaw) } } - vm86_cleanup(&vmState); +out: + biosModule->finish(state); + put_module(B_BIOS_MODULE_NAME); - TRACE("GetEdidFromBIOS() status: 0x%lx\n", status); + TRACE("GetEdidFromBIOS() status: 0x%" B_PRIx32 "\n", status); return status; } diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp index 6e31f6d870..0a3dd14455 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp @@ -9,10 +9,11 @@ #include +#include + #include #include #include -#include #include #include "driver.h" @@ -20,6 +21,43 @@ #include "vesa_info.h" +static bios_module_info* sBIOSModule; + + +/*! Loads the BIOS module and sets up a state for it. The BIOS module is only + loaded when we need it, as it is quite a large module. +*/ +static status_t +vbe_call_prepare(bios_state** state) +{ + status_t status; + + status = get_module(B_BIOS_MODULE_NAME, (module_info**)&sBIOSModule); + if (status != B_OK) { + dprintf(DEVICE_NAME ": failed to get BIOS module: %s\n", + strerror(status)); + return status; + } + + status = sBIOSModule->prepare(state); + if (status != B_OK) { + dprintf(DEVICE_NAME ": failed to prepare BIOS state: %s\n", + strerror(status)); + put_module(B_BIOS_MODULE_NAME); + } + + return status; +} + + +static void +vbe_call_finish(bios_state* state) +{ + sBIOSModule->finish(state); + put_module(B_BIOS_MODULE_NAME); +} + + static status_t find_graphics_card(addr_t frameBuffer, addr_t& base, size_t& size) { @@ -80,26 +118,31 @@ get_color_space_for_depth(uint32 depth) static status_t -vbe_get_mode_info(struct vm86_state& vmState, uint16 mode, - struct vbe_mode_info* modeInfo) +vbe_get_mode_info(bios_state* state, uint16 mode, struct vbe_mode_info* modeInfo) { - struct vbe_mode_info* vbeModeInfo = (struct vbe_mode_info*)0x1000; - + void* vbeModeInfo = sBIOSModule->allocate_mem(state, + sizeof(struct vbe_mode_info)); + if (vbeModeInfo == NULL) + return B_NO_MEMORY; memset(vbeModeInfo, 0, sizeof(vbe_mode_info)); - vmState.regs.eax = 0x4f01; - vmState.regs.ecx = mode; - vmState.regs.es = 0x1000 >> 4; - vmState.regs.edi = 0x0000; - status_t status = vm86_do_int(&vmState, 0x10); + uint32 physicalAddress = sBIOSModule->physical_address(state, vbeModeInfo); + bios_regs regs = {}; + regs.eax = 0x4f01; + regs.ecx = mode; + regs.es = physicalAddress >> 4; + regs.edi = physicalAddress - (regs.es << 4); + + status_t status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): vm86 failed\n", mode); + dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): BIOS failed: %s\n", mode, + strerror(status)); return status; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { - dprintf(DEVICE_NAME ": vbe_get_mode_info(): BIOS returned 0x%04lx\n", - vmState.regs.eax & 0xffff); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vbe_get_mode_info(%u): BIOS returned " + "0x%04" B_PRIx32 "\n", mode, regs.eax & 0xffff); return B_ENTRY_NOT_FOUND; } @@ -109,20 +152,22 @@ vbe_get_mode_info(struct vm86_state& vmState, uint16 mode, static status_t -vbe_set_mode(struct vm86_state& vmState, uint16 mode) +vbe_set_mode(bios_state* state, uint16 mode) { - vmState.regs.eax = 0x4f02; - vmState.regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER; + bios_regs regs = {}; + regs.eax = 0x4f02; + regs.ebx = (mode & SET_MODE_MASK) | SET_MODE_LINEAR_BUFFER; - status_t status = vm86_do_int(&vmState, 0x10); + status_t status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vbe_set_mode(%u): vm86 failed\n", mode); + dprintf(DEVICE_NAME ": vbe_set_mode(%u): BIOS failed: %s\n", mode, + strerror(status)); return status; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { - dprintf(DEVICE_NAME ": vbe_set_mode(): BIOS returned 0x%04lx\n", - vmState.regs.eax & 0xffff); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vbe_set_mode(%u): BIOS returned 0x%04" B_PRIx32 + "\n", mode, regs.eax & 0xffff); return B_ERROR; } @@ -152,64 +197,64 @@ vbe_get_dpms_capabilities(uint32& vbeMode, uint32& mode) vbeMode = 0; mode = B_DPMS_ON; - // Prepare vm86 mode environment - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vbe_get_dpms_capabilities(): vm86_prepare " - "failed: %s\n", strerror(status)); + // Prepare BIOS environment + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; - } - vmState.regs.eax = 0x4f10; - vmState.regs.ebx = 0; - vmState.regs.esi = 0; - vmState.regs.edi = 0; + bios_regs regs = {}; + regs.eax = 0x4f10; + regs.ebx = 0; + regs.esi = 0; + regs.edi = 0; - status = vm86_do_int(&vmState, 0x10); + status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): vm86 failed\n"); + dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS failed: %s\n", + strerror(status)); goto out; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { + if ((regs.eax & 0xffff) != 0x4f) { dprintf(DEVICE_NAME ": vbe_get_dpms_capabilities(): BIOS returned " - "0x%04lx\n", vmState.regs.eax & 0xffff); + "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); status = B_ERROR; goto out; } - vbeMode = vmState.regs.ebx >> 8; + vbeMode = regs.ebx >> 8; mode = vbe_to_system_dpms(vbeMode); out: - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } static status_t -vbe_set_bits_per_gun(vm86_state& vmState, vesa_info& info, uint8 bits) +vbe_set_bits_per_gun(bios_state* state, vesa_info& info, uint8 bits) { info.bits_per_gun = 6; - vmState.regs.eax = 0x4f08; - vmState.regs.ebx = (bits << 8) | 1; + bios_regs regs = {}; + regs.eax = 0x4f08; + regs.ebx = (bits << 8) | 1; - status_t status = vm86_do_int(&vmState, 0x10); + status_t status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): vm86 failed: %s\n", + dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS failed: %s\n", strerror(status)); return status; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { - dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS returned 0x%04lx\n", - vmState.regs.eax & 0xffff); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vbe_set_bits_per_gun(): BIOS returned " + "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); return B_ERROR; } - info.bits_per_gun = vmState.regs.ebx >> 8; + info.bits_per_gun = regs.ebx >> 8; return B_OK; } @@ -219,17 +264,14 @@ vbe_set_bits_per_gun(vesa_info& info, uint8 bits) { info.bits_per_gun = 6; - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vbe_set_bits_per_gun(): vm86_prepare failed: " - "%s\n", strerror(status)); + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; - } - status = vbe_set_bits_per_gun(vmState, info, bits); + status = vbe_set_bits_per_gun(state, info, bits); - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } @@ -386,31 +428,29 @@ vesa_set_display_mode(vesa_info& info, uint32 mode) if (mode >= info.shared_info->vesa_mode_count) return B_ENTRY_NOT_FOUND; - // Prepare vm86 mode environment - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vesa_set_display_mode(): vm86_prepare failed\n"); + // Prepare BIOS environment + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; - } // Get mode information struct vbe_mode_info modeInfo; - status = vbe_get_mode_info(vmState, info.modes[mode].mode, &modeInfo); + status = vbe_get_mode_info(state, info.modes[mode].mode, &modeInfo); if (status != B_OK) { dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot get mode info\n"); goto out; } // Set mode - status = vbe_set_mode(vmState, info.modes[mode].mode); + status = vbe_set_mode(state, info.modes[mode].mode); if (status != B_OK) { dprintf(DEVICE_NAME": vesa_set_display_mode(): cannot set mode\n"); goto out; } if (info.modes[mode].bits_per_pixel <= 8) - vbe_set_bits_per_gun(vmState, info, 8); + vbe_set_bits_per_gun(state, info, 8); // Map new frame buffer if necessary @@ -426,7 +466,7 @@ vesa_set_display_mode(vesa_info& info, uint32 mode) } out: - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } @@ -437,38 +477,36 @@ vesa_get_dpms_mode(vesa_info& info, uint32& mode) mode = B_DPMS_ON; // we always return a valid mode - // Prepare vm86 mode environment - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vesa_get_dpms_mode(): vm86_prepare failed: %s\n", - strerror(status)); + // Prepare BIOS environment + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; - } - vmState.regs.eax = 0x4f10; - vmState.regs.ebx = 2; - vmState.regs.esi = 0; - vmState.regs.edi = 0; + bios_regs regs = {}; + regs.eax = 0x4f10; + regs.ebx = 2; + regs.esi = 0; + regs.edi = 0; - status = vm86_do_int(&vmState, 0x10); + status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): vm86 failed: %s\n", + dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS failed: %s\n", strerror(status)); goto out; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { - dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS returned 0x%04lx\n", - vmState.regs.eax & 0xffff); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vesa_get_dpms_mode(): BIOS returned " + "0x%" B_PRIx32 "\n", regs.eax & 0xffff); status = B_ERROR; goto out; } - mode = vbe_to_system_dpms(vmState.regs.ebx >> 8); + mode = vbe_to_system_dpms(regs.ebx >> 8); out: - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } @@ -489,36 +527,34 @@ vesa_set_dpms_mode(vesa_info& info, uint32 mode) vbeMode &= info.vbe_dpms_capabilities; - // Prepare vm86 mode environment - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vesa_set_dpms_mode(): vm86_prepare failed: %s\n", - strerror(status)); + // Prepare BIOS environment + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; - } - vmState.regs.eax = 0x4f10; - vmState.regs.ebx = (vbeMode << 8) | 1; - vmState.regs.esi = 0; - vmState.regs.edi = 0; + bios_regs regs = {}; + regs.eax = 0x4f10; + regs.ebx = (vbeMode << 8) | 1; + regs.esi = 0; + regs.edi = 0; - status = vm86_do_int(&vmState, 0x10); + status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): vm86 failed: %s\n", + dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS failed: %s\n", strerror(status)); goto out; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { - dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS returned 0x%04lx\n", - vmState.regs.eax & 0xffff); + if ((regs.eax & 0xffff) != 0x4f) { + dprintf(DEVICE_NAME ": vesa_set_dpms_mode(): BIOS returned " + "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); status = B_ERROR; goto out; } out: - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } @@ -527,26 +563,33 @@ status_t vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8* colors, uint16 count) { + bios_regs regs = {}; + uint32 shift, physicalAddress; + if (first + count > 256) count = 256 - first; - // Prepare vm86 mode environment - struct vm86_state vmState; - status_t status = vm86_prepare(&vmState, 0x20000); - if (status != B_OK) { - dprintf(DEVICE_NAME": vesa_set_indexed_colors(): vm86_prepare failed: " - "%s\n", strerror(status)); + // Prepare BIOS environment + bios_state* state; + status_t status = vbe_call_prepare(&state); + if (status != B_OK) return status; + + uint8* palette = (uint8*)sBIOSModule->allocate_mem(state, 256 * 4); + if (palette == NULL) { + status = B_NO_MEMORY; + goto out; } - uint8* palette = (uint8*)0x1000; - uint32 shift = 8 - info.bits_per_gun; + shift = 8 - info.bits_per_gun; // convert colors to VESA palette for (int32 i = first; i < count; i++) { uint8 color[3]; - if (user_memcpy(color, &colors[i * 3], 3) < B_OK) - return B_BAD_ADDRESS; + if (user_memcpy(color, &colors[i * 3], 3) < B_OK) { + status = B_BAD_ADDRESS; + goto out; + } // order is BGR- palette[i * 4 + 0] = color[2] >> shift; @@ -556,27 +599,28 @@ vesa_set_indexed_colors(vesa_info& info, uint8 first, uint8* colors, } // set palette - vmState.regs.eax = 0x4f09; - vmState.regs.ebx = 0; - vmState.regs.ecx = count; - vmState.regs.edx = first; - vmState.regs.es = 0x1000 >> 4; - vmState.regs.edi = 0x0000; + physicalAddress = sBIOSModule->physical_address(state, palette); + regs.eax = 0x4f09; + regs.ebx = 0; + regs.ecx = count; + regs.edx = first; + regs.es = physicalAddress >> 4; + regs.edi = physicalAddress - (regs.es << 4); - status = vm86_do_int(&vmState, 0x10); + status = sBIOSModule->interrupt(state, 0x10, ®s); if (status != B_OK) { - dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): vm86 failed: %s\n", + dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): BIOS failed: %s\n", strerror(status)); goto out; } - if ((vmState.regs.eax & 0xffff) != 0x4f) { + if ((regs.eax & 0xffff) != 0x4f) { dprintf(DEVICE_NAME ": vesa_set_indexed_colors(): BIOS returned " - "0x%04lx\n", vmState.regs.eax & 0xffff); + "0x%04" B_PRIx32 "\n", regs.eax & 0xffff); status = B_ERROR; } out: - vm86_cleanup(&vmState); + vbe_call_finish(state); return status; } From 74bda98cb236130b1d4f84795f7fafd5c8e540a9 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 3 Aug 2012 16:49:15 +0100 Subject: [PATCH 160/273] Killed off vm86 code, no longer being used. --- headers/private/kernel/arch/x86/32/iframe.h | 32 - headers/private/kernel/arch/x86/vm86.h | 42 -- src/system/kernel/arch/x86/32/int.cpp | 1 - src/system/kernel/arch/x86/32/interrupts.S | 109 ---- src/system/kernel/arch/x86/32/vm86.cpp | 668 -------------------- src/system/kernel/arch/x86/Jamfile | 1 - src/system/kernel/arch/x86/arch_int.cpp | 9 - src/system/kernel/arch/x86/asm_offsets.cpp | 4 - 8 files changed, 866 deletions(-) delete mode 100644 headers/private/kernel/arch/x86/vm86.h delete mode 100644 src/system/kernel/arch/x86/32/vm86.cpp diff --git a/headers/private/kernel/arch/x86/32/iframe.h b/headers/private/kernel/arch/x86/32/iframe.h index 1aa51ed90a..47c423826f 100644 --- a/headers/private/kernel/arch/x86/32/iframe.h +++ b/headers/private/kernel/arch/x86/32/iframe.h @@ -37,40 +37,8 @@ struct iframe { uint32 user_ss; }; -struct vm86_iframe { - uint32 type; // iframe type - uint32 __null_gs; - uint32 __null_fs; - uint32 __null_es; - uint32 __null_ds; - uint32 edi; - uint32 esi; - uint32 ebp; - uint32 __kern_esp; - uint32 ebx; - uint32 edx; - uint32 ecx; - uint32 eax; - uint32 orig_eax; - uint32 orig_edx; - uint32 vector; - uint32 error_code; - uint32 eip; - uint16 cs, __csh; - uint32 flags; - uint32 esp; - uint16 ss, __ssh; - - /* vm86 mode specific part */ - uint16 es, __esh; - uint16 ds, __dsh; - uint16 fs, __fsh; - uint16 gs, __gsh; -}; - #define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ || ((f)->flags & 0x20000) != 0) -#define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) #endif /* _KERNEL_ARCH_X86_32_IFRAME_H */ diff --git a/headers/private/kernel/arch/x86/vm86.h b/headers/private/kernel/arch/x86/vm86.h deleted file mode 100644 index 7e4692da48..0000000000 --- a/headers/private/kernel/arch/x86/vm86.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2008 Jan Klötzke - * All rights reserved. Distributed under the terms of the MIT License. - */ -#ifndef _VM86_H -#define _VM86_H - - -#ifndef __x86_64__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define VM86_MIN_RAM_SIZE 0x1000 -#define RETURN_TO_32_INT 255 - -struct vm86_state { - struct vm86_iframe regs; - area_id bios_area; - area_id ram_area; - unsigned int if_flag : 1; -}; - -status_t x86_vm86_enter(struct vm86_iframe *frame); -void x86_vm86_return(struct vm86_iframe *frame, status_t retval); - -status_t vm86_prepare(struct vm86_state *state, unsigned int ram_size); -void vm86_cleanup(struct vm86_state *state); -status_t vm86_do_int(struct vm86_state *state, uint8 vec); - -#ifdef __cplusplus -} -#endif - -#endif -#endif - - diff --git a/src/system/kernel/arch/x86/32/int.cpp b/src/system/kernel/arch/x86/32/int.cpp index d718623538..e05305d8d8 100644 --- a/src/system/kernel/arch/x86/32/int.cpp +++ b/src/system/kernel/arch/x86/32/int.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include "interrupts.h" diff --git a/src/system/kernel/arch/x86/32/interrupts.S b/src/system/kernel/arch/x86/32/interrupts.S index ea3cd5e5a4..5fde6b901e 100644 --- a/src/system/kernel/arch/x86/32/interrupts.S +++ b/src/system/kernel/arch/x86/32/interrupts.S @@ -516,8 +516,6 @@ STATIC_FUNCTION(int_bottom): // exception. orl $0x10000, IFRAME_flags(%ebp); - testl $0x20000, IFRAME_flags(%ebp) // VM86 mode - jnz int_bottom_vm86 cmp $USER_CODE_SEG, IFRAME_cs(%ebp) // user mode je int_bottom_user @@ -583,36 +581,6 @@ STATIC_FUNCTION(int_bottom_user): FUNCTION_END(int_bottom_user) -STATIC_FUNCTION(int_bottom_vm86): - movl $KERNEL_DATA_SEG,%eax - cld - movl %eax,%ds - movl %eax,%es - - // update the thread's user time - movl %dr3, %edi // thread pointer - cli - UPDATE_THREAD_USER_TIME() - - // leave interrupts disabled -- the handler will enable them, if - // necessary - - pushl %ebp - movl IFRAME_vector(%ebp), %eax - call *gInterruptHandlerTable(, %eax, 4) - - cli // disable interrupts - - // update the thread's kernel time and return - UPDATE_THREAD_KERNEL_TIME() - - // the above will reset the in_kernel flag to 0, but we actually stay - movb $1, THREAD_in_kernel(%edi); - - POP_IFRAME_AND_RETURN() -FUNCTION_END(int_bottom_vm86) - - // test interrupt handler for performance measurements .align 16 FUNCTION(trap98): @@ -856,80 +824,3 @@ FUNCTION(x86_return_to_userland): UPDATE_THREAD_KERNEL_TIME() POP_IFRAME_AND_RETURN() FUNCTION_END(x86_return_to_userland) - - -/* status_t x86_vm86_enter(struct vm86_iframe *frame) */ -FUNCTION(x86_vm86_enter): - // save critical registers - pushf - pushl %edi - pushl %esi - pushl %ebp - pushl %ebx - push %gs - push %fs - - // get pointers - movl 32(%esp), %esi // vm86 iframe - pushl %esi // ... store iframe addr for x86_vm86_return - movl %dr3, %edi // Thread* - - // make sure eflags are in right shape - movl VM86_IFRAME_flags(%esi), %eax - andl $0x200CD5, %eax // leave ID,OF,DF,SF,ZF,AF,PF,CF flags - orl $0x20202, %eax // set VM and IF flags (+10b) - movl %eax, VM86_IFRAME_flags(%esi) - - // update kernel_stack_top and tss.esp0 - pushl THREAD_kernel_stack_top(%edi) - movl %esp, THREAD_kernel_stack_top(%edi) - pushl %esp - call x86_set_tss_and_kstack - - // go to vm86 mode - cli - UPDATE_THREAD_KERNEL_TIME() - lea 20(%esi), %esp - popa - addl $16, %esp - iret -FUNCTION_END(x86_vm86_enter) - - -/* void x86_vm86_return(struct vm86_iframe *frame, status_t retval) */ -FUNCTION(x86_vm86_return): - // set stack to where x86_vm86_enter was left - movl 8(%esp), %ebx - movl 4(%esp), %esi - cli - movl %esi, %esp - addl $VM86_IFRAME_sizeof, %esp - - // save old iframe - popl %eax // old kernel stack top - popl %edi - movl $(VM86_IFRAME_sizeof >> 2), %ecx - cld - rep movsl - - // adjust kernel_stack_top and tss.esp0 - movl %dr3, %edi - movl %eax, THREAD_kernel_stack_top(%edi) - pushl %eax - call x86_set_tss_and_kstack - addl $4, %esp - - // restore registers - movl %ebx, %eax - - // we skip %fs, as this contains the CPU dependent TLS segment - addl $4, %esp; - - pop %gs - popl %ebx - popl %ebp - popl %esi - popl %edi - popf - ret -FUNCTION_END(x86_vm86_return) diff --git a/src/system/kernel/arch/x86/32/vm86.cpp b/src/system/kernel/arch/x86/32/vm86.cpp deleted file mode 100644 index 948b701019..0000000000 --- a/src/system/kernel/arch/x86/32/vm86.cpp +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright 2008 Jan Klötzke - * All rights reserved. Distributed under the terms of the MIT License. - * - * Emulation based on the Linux Real Mode Interface library. - * Copyright (C) 1998 by Josh Vanderhoof - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -//#define TRACE_VM86 -#ifdef TRACE_VM86 -# define TRACE(x...) dprintf("[vm86] " x) -# define TRACE_NP(x...) dprintf(x) -#else -# define TRACE(x...) -# define TRACE_NP(x...) -#endif - -#define CLI 0xfa -#define INB 0xec -#define INBI 0xe4 -#define INSB 0x6c -#define INSW 0x6d -#define INTn 0xcd -#define INW 0xed -#define INWI 0xe5 -#define IRET 0xcf -#define OUTB 0xee -#define OUTBI 0xe6 -#define OUTSB 0x6e -#define OUTSW 0x6f -#define OUTW 0xef -#define OUTWI 0xe7 -#define POPF 0x9d -#define PUSHF 0x9c -#define STI 0xfb - -#define I_FLAG (1u << 9) -#define DIRECTION_FLAG (1u << 10) - -#define CSEG 0x2e -#define SSEG 0x36 -#define DSEG 0x3e -#define ESEG 0x26 -#define FSEG 0x64 -#define GSEG 0x65 - - -static inline uint16 -get_int_seg(int i) -{ - return *(uint16 *)(i * 4 + 2); -} - - -static inline uint16 -get_int_off(int i) -{ - return *(uint16 *)(i * 4); -} - - -static inline void -pushw(struct vm86_iframe *regs, uint16 i) -{ - regs->esp -= 2; - *(uint16 *)(((uint32)regs->ss << 4) + regs->esp) = i; -} - - -static inline void -pushl(struct vm86_iframe *regs, uint32 i) -{ - regs->esp -= 4; - *(uint32 *)(((uint32)regs->ss << 4) + regs->esp) = i; -} - - -static inline uint16 -popw(struct vm86_iframe *regs) -{ - uint16 ret = *(uint16 *)(((uint32)regs->ss << 4) + regs->esp); - regs->esp += 2; - return ret; -} - - -static inline uint32 -popl(struct vm86_iframe *regs) -{ - uint32 ret = *(uint32 *)(((uint32)regs->ss << 4) + regs->esp); - regs->esp += 4; - return ret; -} - - -static void -em_ins(struct vm86_iframe *regs, int size) -{ - unsigned int edx, edi; - - edx = regs->edx & 0xffff; - edi = regs->edi & 0xffff; - edi += (unsigned int)regs->es << 4; - - if (regs->flags & DIRECTION_FLAG) { - if (size == 4) - asm volatile ("std; insl; cld" : "=D" (edi) : "d" (edx), "0" (edi)); - else if (size == 2) - asm volatile ("std; insw; cld" : "=D" (edi) : "d" (edx), "0" (edi)); - else - asm volatile ("std; insb; cld" : "=D" (edi) : "d" (edx), "0" (edi)); - } else { - if (size == 4) - asm volatile ("cld; insl" : "=D" (edi) : "d" (edx), "0" (edi)); - else if (size == 2) - asm volatile ("cld; insw" : "=D" (edi) : "d" (edx), "0" (edi)); - else - asm volatile ("cld; insb" : "=D" (edi) : "d" (edx), "0" (edi)); - } - - edi -= (unsigned int)regs->es << 4; - - regs->edi &= 0xffff0000; - regs->edi |= edi & 0xffff; -} - - -static void -em_rep_ins(struct vm86_iframe *regs, int size) -{ - unsigned int cx; - - cx = regs->ecx & 0xffff; - - while (cx--) - em_ins(regs, size); - - regs->ecx &= 0xffff0000; -} - - -static void -em_outs(struct vm86_iframe *regs, int size, int seg) -{ - unsigned int edx, esi, base; - - edx = regs->edx & 0xffff; - esi = regs->esi & 0xffff; - - switch (seg) { - case CSEG: base = regs->cs; break; - case SSEG: base = regs->ss; break; - case ESEG: base = regs->es; break; - case FSEG: base = regs->fs; break; - case GSEG: base = regs->gs; break; - case DSEG: - default: - base = regs->ds; - break; - } - - esi += base << 4; - - if (regs->flags & DIRECTION_FLAG) { - if (size == 4) { - asm volatile ("std; outsl; cld" - : "=S" (esi) : "d" (edx), "0" (esi)); - } else if (size == 2) { - asm volatile ("std; outsw; cld" - : "=S" (esi) : "d" (edx), "0" (esi)); - } else { - asm volatile ("std; outsb; cld" - : "=S" (esi) : "d" (edx), "0" (esi)); - } - } else { - if (size == 4) - asm volatile ("cld; outsl" : "=S" (esi) : "d" (edx), "0" (esi)); - else if (size == 2) - asm volatile ("cld; outsw" : "=S" (esi) : "d" (edx), "0" (esi)); - else - asm volatile ("cld; outsb" : "=S" (esi) : "d" (edx), "0" (esi)); - } - - esi -= base << 4; - - regs->esi &= 0xffff0000; - regs->esi |= esi & 0xffff; -} - - -static void -em_rep_outs(struct vm86_iframe *regs, int size, int seg) -{ - unsigned int cx; - - cx = regs->ecx & 0xffff; - - while (cx--) - em_outs(regs, size, seg); - - regs->ecx &= 0xffff0000; -} - - -static inline void -em_inb(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("inb %w1, %b0" - : "=a" (regs->eax) - : "d" (port), "0" (regs->eax)); -} - - -static inline void -em_inw(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("inw %w1, %w0" - : "=a" (regs->eax) - : "d" (port), "0" (regs->eax)); -} - - -static inline void -em_inl(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("inl %w1, %0" : "=a" (regs->eax) : "d" (port)); -} - - -static inline void -em_outb(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("outb %b0, %w1" : : "a" (regs->eax), "d" (port)); -} - - -static inline void -em_outw(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("outw %w0, %w1" : : "a" (regs->eax), "d" (port)); -} - - -static inline void -em_outl(struct vm86_iframe *regs, uint32 port) -{ - asm volatile ("outl %0, %w1" : : "a" (regs->eax), "d" (port)); -} - - -static int -emulate(struct vm86_state *state) -{ - unsigned char *instruction; - struct { - unsigned char seg; - unsigned int size : 1; - unsigned int rep : 1; - } prefix = { DSEG, 0, 0 }; - int ret = 0; - - instruction = (unsigned char *)((unsigned int)state->regs.cs << 4); - instruction += state->regs.eip; - - TRACE("emulate: "); - - /* handle prefixes */ - do { - switch (*instruction) { - case 0x66: - TRACE_NP("[SIZE] "); - prefix.size = 1 - prefix.size; - state->regs.eip++; - instruction++; - break; - case 0xf3: - TRACE_NP("REP "); - prefix.rep = 1; - state->regs.eip++; - instruction++; - break; - case CSEG: - case SSEG: - case DSEG: - case ESEG: - case FSEG: - case GSEG: - TRACE_NP("SEG(0x%02x) ", *instruction); - prefix.seg = *instruction; - state->regs.eip++; - instruction++; - break; - case 0xf0: - case 0xf2: - case 0x67: - /* these prefixes are just ignored */ - TRACE_NP("IGN(0x%02x) ", *instruction); - state->regs.eip++; - instruction++; - break; - default: - ret = 1; - } - } while (!ret); - - /* handle actual instruction */ - ret = 0; - switch (*instruction) { - case INSB: - TRACE_NP("INSB"); - if (prefix.rep) - em_rep_ins(&state->regs, 1); - else - em_ins(&state->regs, 1); - state->regs.eip++; - break; - case INSW: - TRACE_NP("INSW"); - if (prefix.rep) { - if (prefix.size) - em_rep_ins(&state->regs, 4); - else - em_rep_ins(&state->regs, 2); - } else { - if (prefix.size) - em_ins(&state->regs, 4); - else - em_ins(&state->regs, 2); - } - state->regs.eip++; - break; - case OUTSB: - TRACE_NP("OUTSB"); - if (prefix.rep) - em_rep_outs(&state->regs, 1, prefix.seg); - else - em_outs(&state->regs, 1, prefix.seg); - state->regs.eip++; - break; - case OUTSW: - TRACE_NP("OUTSW"); - if (prefix.rep) { - if (prefix.size) - em_rep_outs(&state->regs, 4, prefix.seg); - else - em_rep_outs(&state->regs, 2, prefix.seg); - } else { - if (prefix.size) - em_outs(&state->regs, 4, prefix.seg); - else - em_outs(&state->regs, 2, prefix.seg); - } - state->regs.eip++; - break; - case INBI: - em_inb(&state->regs, instruction[1]); - TRACE_NP("IN al(=0x%02lx), 0x%02x", state->regs.eax & 0xff, - instruction[1]); - state->regs.eip += 2; - break; - case INWI: - if (prefix.size) { - em_inl(&state->regs, instruction[1]); - TRACE_NP("IN eax(=0x%08lx), 0x%02x", state->regs.eax, - instruction[1]); - } else { - em_inw(&state->regs, instruction[1]); - TRACE_NP("IN ax(=0x%04lx), 0x%02x", state->regs.eax & 0xffff, - instruction[1]); - } - state->regs.eip += 2; - break; - case INB: - em_inb(&state->regs, state->regs.edx); - TRACE_NP("IN al(=0x%02lx), dx(0x%04lx)", state->regs.edx & 0xff, - state->regs.edx & 0xffff); - state->regs.eip++; - break; - case INW: - if (prefix.size) { - em_inl(&state->regs, state->regs.edx); - TRACE_NP("IN eax(=0x%08lx), dx(0x%04lx)", state->regs.edx, - state->regs.edx & 0xffff); - } else { - em_inw(&state->regs, state->regs.edx); - TRACE_NP("IN ax(=0x%04lx), dx(0x%04lx)", - state->regs.edx & 0xffff, state->regs.edx & 0xffff); - } - state->regs.eip++; - break; - case OUTBI: - em_outb(&state->regs, instruction[1]); - TRACE_NP("OUT 0x%02x, al(0x%02lx)", instruction[1], - state->regs.eax & 0xff); - state->regs.eip += 2; - break; - case OUTWI: - if (prefix.size) { - em_outl(&state->regs, instruction[1]); - TRACE_NP("OUT 0x%02x, eax(0x%08lx)", instruction[1], - state->regs.eax); - } else { - em_outw(&state->regs, instruction[1]); - TRACE_NP("OUT 0x%02x, ax(0x%04lx)", instruction[1], - state->regs.eax & 0xffff); - } - state->regs.eip += 2; - break; - case OUTB: - em_outb(&state->regs, state->regs.edx); - TRACE_NP("OUT dx(0x%04lx), al(0x%02lx)", state->regs.edx & 0xffff, - state->regs.eax & 0xff); - state->regs.eip++; - break; - case OUTW: - if (prefix.size) { - em_outl(&state->regs, state->regs.edx); - TRACE_NP("OUT dx(0x%04lx), eax(0x%08lx)", - state->regs.edx & 0xffff, state->regs.eax); - } else { - em_outw(&state->regs, state->regs.edx); - TRACE_NP("OUT dx(0x%04lx), ax(0x%04lx)", - state->regs.edx & 0xffff, state->regs.eax & 0xffff); - } - state->regs.eip++; - break; - case INTn: - TRACE_NP("INT 0x%02x", instruction[1]); - if (instruction[1] == RETURN_TO_32_INT) { - ret = 1; - } else { - uint16 flags = state->regs.flags; - - /* store real IF */ - flags &= ~I_FLAG; - flags |= (uint16)state->if_flag << 9; - - pushw(&state->regs, flags); - pushw(&state->regs, state->regs.cs); - pushw(&state->regs, state->regs.eip + 2); - - state->regs.cs = get_int_seg(instruction[1]); - state->regs.eip = get_int_off(instruction[1]); - state->if_flag = 0; - } - break; - case IRET: - TRACE_NP("IRET"); - state->regs.eip = popw(&state->regs); - state->regs.cs = popw(&state->regs); - state->regs.flags = popw(&state->regs); - /* restore IF */ - state->if_flag = (state->regs.flags >> 9) & 0x01; - break; - case CLI: - TRACE_NP("CLI"); - state->if_flag = 0; - state->regs.eip++; - break; - case STI: - TRACE_NP("STI"); - state->if_flag = 1; - state->regs.eip++; - break; - case PUSHF: - { - TRACE_NP("PUSHF"); - uint32 flags = state->regs.flags; - - /* store real IF */ - flags &= ~I_FLAG; - flags |= (uint32)state->if_flag << 9; - if (prefix.size) - pushl(&state->regs, flags); - else - pushw(&state->regs, flags); - state->regs.eip++; - break; - } - case POPF: - { - TRACE_NP("POPF"); - if (prefix.size) - state->regs.flags = popl(&state->regs); - else - state->regs.flags = popw(&state->regs); - /* restore IF */ - state->if_flag = (state->regs.flags >> 9) & 0x01; - state->regs.eip++; - break; - } - default: - TRACE_NP("UNK"); - ret = -1; - } - - TRACE_NP("\n"); - return ret; -} - - -static bool -vm86_fault_callback(addr_t address, addr_t faultAddress, bool isWrite) -{ - struct iframe *frame = x86_get_user_iframe(); - - TRACE("Unhandled fault at %#" B_PRIxADDR " touching %#" B_PRIxADDR - "while %s\n", faultAddress, address, isWrite ? "writing" : "reading"); - - // we shouldn't have unhandled page faults in vm86 mode - x86_vm86_return((struct vm86_iframe *)frame, B_BAD_ADDRESS); - - // not reached - return false; -} - - -// #pragma mark - exported interface - - -/*! Prepare the thread to execute BIOS code in virtual 8086 mode. Initializes - the given \a state to default values and maps the BIOS into the teams - address space. The size of the available conventional RAM is given in - \a ramSize in bytes which should be greater or equal to VM86_MIN_RAM_SIZE. -*/ -extern "C" status_t -vm86_prepare(struct vm86_state *state, unsigned int ramSize) -{ - Team *team = thread_get_current_thread()->team; - status_t ret = B_OK; - area_id vectors; - - state->bios_area = B_ERROR; - - // create RAM area - if (ramSize < VM86_MIN_RAM_SIZE) - ramSize = VM86_MIN_RAM_SIZE; - - void *address; - virtual_address_restrictions virtualRestrictions = {}; - virtualRestrictions.address = NULL; - virtualRestrictions.address_specification = B_EXACT_ADDRESS; - physical_address_restrictions physicalRestrictions = {}; - state->ram_area = create_area_etc(team->id, "dos", ramSize, B_NO_LOCK, - B_READ_AREA | B_WRITE_AREA, 0, &virtualRestrictions, - &physicalRestrictions, &address); - if (state->ram_area < B_OK) { - ret = state->ram_area; - TRACE("Could not create RAM area\n"); - goto error; - } - - // copy int vectors and BIOS data area - vectors = map_physical_memory("int vectors", 0, 0x502, - B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, - &address); - if (vectors < B_OK) { - ret = vectors; - TRACE("Could not copy vectors\n"); - goto error; - } - ret = user_memcpy((void *)0, address, 0x502); - *((uint32 *)0) = 0xdeadbeef; - delete_area(vectors); - if (ret != B_OK) - goto error; - - // map vga/bios area - address = (void *)0xa0000; - state->bios_area = vm_map_physical_memory(team->id, "bios", - &address, B_EXACT_ADDRESS, 0x60000, - B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA, - (addr_t)0xa0000, false); - if (state->bios_area < B_OK) { - ret = state->bios_area; - TRACE("Could not map VGA BIOS.\n"); - goto error; - } - - return B_OK; - -error: - if (state->bios_area > B_OK) - vm_delete_area(team->id, state->bios_area, true); - if (state->ram_area > B_OK) - vm_delete_area(team->id, state->ram_area, true); - return ret; -} - - -/*! Free ressources which were allocated by vm86_prepare(). -*/ -extern "C" void -vm86_cleanup(struct vm86_state *state) -{ - Team *team = thread_get_current_thread()->team; - - if (state->bios_area > B_OK) - vm_delete_area(team->id, state->bios_area, true); - if (state->ram_area > B_OK) - vm_delete_area(team->id, state->ram_area, true); -} - - -/*! Execute a BIOS call of interrupt \a vec. The given \a state must be - initialized by vm86_prepare() before, any registers needed by the BIOS too. - - The function will return B_OK if the BIOS was called successfully, - otherwise an apropriate error code. After the call the registers are - copied back to \a state to reflect the status after the BIOS returned. - - Any buffer which is given to the BIOS function may be allocated starting - from address 0x1000 up to the allocated RAM size (see vm86_prepare()). The - area below 0x1000 is not available because it is used for the interrupt - vector table, BIOS data area and as real mode stack. -*/ -extern "C" status_t -vm86_do_int(struct vm86_state *state, uint8 vec) -{ - int8 *ip; - int emuState = 0; - Thread *thread = thread_get_current_thread(); - status_t ret; - - // prepare environment - state->regs.ss = 0x600 >> 4; - state->regs.esp = (0x1000 - 0x600); - state->regs.cs = get_int_seg(vec); - state->regs.eip = get_int_off(vec); - state->if_flag = 0; - - pushw(&state->regs, state->regs.flags); - pushw(&state->regs, 0x0000); /* CS */ - pushw(&state->regs, 0x0600); /* IP */ - - ip = (int8 *)0x600; - *ip++ = INTn; - *ip++ = RETURN_TO_32_INT; - - // execute interrupt - thread->fault_callback = &vm86_fault_callback; - do { - ret = x86_vm86_enter(&state->regs); - if (ret != B_OK) - break; - emuState = emulate(state); - } while (emuState == 0); - thread->fault_callback = NULL; - - // We might have clobbered %fs, so we need to restore the CPU dependent - // TLS context that we may have overwritten. Note that we can't simply - // restore %fs to its previous value as we might not run on the same CPU - // anymore. - x86_set_tls_context(thread); - - return emuState < 0 ? B_BAD_DATA : ret; -} - diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index ccab5f8f02..745f69b8fa 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -55,7 +55,6 @@ if $(TARGET_ARCH) = x86_64 { syscalls.cpp syscalls_asm.S thread.cpp - vm86.cpp arch_user_debugger.cpp ioapic.cpp diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index f604defdb1..c1340f1060 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include @@ -109,14 +108,6 @@ x86_unexpected_exception(iframe* frame) addr_t signalAddress = 0; int32 signalError = B_ERROR; -#ifndef __x86_64__ - if (IFRAME_IS_VM86(frame)) { - x86_vm86_return((vm86_iframe*)frame, (frame->vector == 13) ? - B_OK : B_ERROR); - // won't get here - } -#endif - switch (frame->vector) { case 0: // Divide Error Exception (#DE) type = B_DIVIDE_ERROR; diff --git a/src/system/kernel/arch/x86/asm_offsets.cpp b/src/system/kernel/arch/x86/asm_offsets.cpp index 42f7bc9a48..88082f90ce 100644 --- a/src/system/kernel/arch/x86/asm_offsets.cpp +++ b/src/system/kernel/arch/x86/asm_offsets.cpp @@ -68,10 +68,6 @@ dummy() DEFINE_OFFSET_MACRO(IFRAME, iframe, r10); #else DEFINE_OFFSET_MACRO(IFRAME, iframe, orig_eax); - - // struct vm86_iframe - DEFINE_SIZEOF_MACRO(VM86_IFRAME, vm86_iframe); - DEFINE_OFFSET_MACRO(VM86_IFRAME, vm86_iframe, flags); #endif // struct syscall_info From 9bfe064799922abfaa9e139b8d59ce0a01914715 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Fri, 3 Aug 2012 17:12:53 +0100 Subject: [PATCH 161/273] GCC 2 compilation fix for x86emu. --- src/add-ons/kernel/generic/bios/x86emu/ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/generic/bios/x86emu/ops.c b/src/add-ons/kernel/generic/bios/x86emu/ops.c index 76b83581f5..8af1df47a8 100644 --- a/src/add-ons/kernel/generic/bios/x86emu/ops.c +++ b/src/add-ons/kernel/generic/bios/x86emu/ops.c @@ -10189,8 +10189,8 @@ Handles opcode 0xe8 static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1)) { - s16 ip16; - s32 ip32; + s16 ip16 = 0; + s32 ip32 = 0; START_OF_INSTR(); DECODE_PRINTF("CALL\t"); From 92f09f1aebbed0b5a9a24925ff3edf2c5180e7ff Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 4 Aug 2012 10:14:22 +0100 Subject: [PATCH 162/273] Added AHCI driver to image. --- build/jam/Haiku64Image | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index c841c2322d..7f4f1b05a5 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -60,6 +60,8 @@ if $(HAIKU_ATA_STACK) = 1 { : generic_ide_pci ; } +AddFilesToHaikuImage system add-ons kernel busses scsi + : ahci ; AddFilesToHaikuImage system add-ons kernel debugger : demangle ; AddFilesToHaikuImage system add-ons kernel file_systems @@ -212,7 +214,7 @@ AddFilesToHaikuImage system : haiku_loader ; # boot module links AddBootModuleSymlinksToHaikuImage $(ATA_ONLY)ata pci config_manager dpc scsi $(ATA_ONLY)ata_adapter - locked_pool scsi_periph generic_ide_pci scsi_cd scsi_disk intel + locked_pool scsi_periph ahci generic_ide_pci scsi_cd scsi_disk intel bfs ; From 70ee5a7efb6b566d840437a24edf0264e4d6c2ee Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 4 Aug 2012 10:21:22 +0100 Subject: [PATCH 163/273] Moved x86emu to {src,headers}/libs/. --- .../kernel/generic/bios => headers/libs}/x86emu/x86emu.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/debug.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/decode.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/fpu.h | 0 .../bios => headers/libs}/x86emu/x86emu/fpu_regs.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/ops.h | 0 .../bios => headers/libs}/x86emu/x86emu/prim_asm.h | 0 .../bios => headers/libs}/x86emu/x86emu/prim_ops.h | 0 .../bios => headers/libs}/x86emu/x86emu/prim_x86_gcc.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/regs.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/types.h | 0 .../generic/bios => headers/libs}/x86emu/x86emu/x86emui.h | 0 src/add-ons/kernel/generic/bios/Jamfile | 8 +++++++- src/{add-ons/kernel/generic/bios => libs}/x86emu/debug.c | 0 src/{add-ons/kernel/generic/bios => libs}/x86emu/decode.c | 0 src/{add-ons/kernel/generic/bios => libs}/x86emu/fpu.c | 0 src/{add-ons/kernel/generic/bios => libs}/x86emu/ops.c | 0 src/{add-ons/kernel/generic/bios => libs}/x86emu/ops2.c | 0 .../kernel/generic/bios => libs}/x86emu/prim_ops.c | 0 src/{add-ons/kernel/generic/bios => libs}/x86emu/sys.c | 0 .../kernel/generic/bios => libs}/x86emu/validate.c | 0 21 files changed, 7 insertions(+), 1 deletion(-) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/debug.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/decode.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/fpu.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/fpu_regs.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/ops.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/prim_asm.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/prim_ops.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/prim_x86_gcc.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/regs.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/types.h (100%) rename {src/add-ons/kernel/generic/bios => headers/libs}/x86emu/x86emu/x86emui.h (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/debug.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/decode.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/fpu.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/ops.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/ops2.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/prim_ops.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/sys.c (100%) rename src/{add-ons/kernel/generic/bios => libs}/x86emu/validate.c (100%) diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu.h b/headers/libs/x86emu/x86emu.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu.h rename to headers/libs/x86emu/x86emu.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h b/headers/libs/x86emu/x86emu/debug.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/debug.h rename to headers/libs/x86emu/x86emu/debug.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h b/headers/libs/x86emu/x86emu/decode.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/decode.h rename to headers/libs/x86emu/x86emu/decode.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h b/headers/libs/x86emu/x86emu/fpu.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu.h rename to headers/libs/x86emu/x86emu/fpu.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h b/headers/libs/x86emu/x86emu/fpu_regs.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/fpu_regs.h rename to headers/libs/x86emu/x86emu/fpu_regs.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h b/headers/libs/x86emu/x86emu/ops.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/ops.h rename to headers/libs/x86emu/x86emu/ops.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h b/headers/libs/x86emu/x86emu/prim_asm.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_asm.h rename to headers/libs/x86emu/x86emu/prim_asm.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h b/headers/libs/x86emu/x86emu/prim_ops.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_ops.h rename to headers/libs/x86emu/x86emu/prim_ops.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h b/headers/libs/x86emu/x86emu/prim_x86_gcc.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/prim_x86_gcc.h rename to headers/libs/x86emu/x86emu/prim_x86_gcc.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h b/headers/libs/x86emu/x86emu/regs.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/regs.h rename to headers/libs/x86emu/x86emu/regs.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h b/headers/libs/x86emu/x86emu/types.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/types.h rename to headers/libs/x86emu/x86emu/types.h diff --git a/src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h b/headers/libs/x86emu/x86emu/x86emui.h similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/x86emu/x86emui.h rename to headers/libs/x86emu/x86emu/x86emui.h diff --git a/src/add-ons/kernel/generic/bios/Jamfile b/src/add-ons/kernel/generic/bios/Jamfile index faa5ec4370..cab1336c9c 100644 --- a/src/add-ons/kernel/generic/bios/Jamfile +++ b/src/add-ons/kernel/generic/bios/Jamfile @@ -1,17 +1,23 @@ SubDir HAIKU_TOP src add-ons kernel generic bios ; +UseHeaders [ LibraryHeaders x86emu ] ; UsePrivateKernelHeaders ; SEARCH_SOURCE += [ FDirName $(SUBDIR) x86emu ] ; -KernelAddon bios : +local x86emuSources = decode.c fpu.c ops.c ops2.c prim_ops.c sys.c +; +KernelAddon bios : + $(x86emuSources) bios.cpp ; +SEARCH on [ FGristFiles $(x86emuSources) ] + = [ FDirName $(HAIKU_TOP) src libs x86emu ] ; diff --git a/src/add-ons/kernel/generic/bios/x86emu/debug.c b/src/libs/x86emu/debug.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/debug.c rename to src/libs/x86emu/debug.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/decode.c b/src/libs/x86emu/decode.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/decode.c rename to src/libs/x86emu/decode.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/fpu.c b/src/libs/x86emu/fpu.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/fpu.c rename to src/libs/x86emu/fpu.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/ops.c b/src/libs/x86emu/ops.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/ops.c rename to src/libs/x86emu/ops.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/ops2.c b/src/libs/x86emu/ops2.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/ops2.c rename to src/libs/x86emu/ops2.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/prim_ops.c b/src/libs/x86emu/prim_ops.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/prim_ops.c rename to src/libs/x86emu/prim_ops.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/sys.c b/src/libs/x86emu/sys.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/sys.c rename to src/libs/x86emu/sys.c diff --git a/src/add-ons/kernel/generic/bios/x86emu/validate.c b/src/libs/x86emu/validate.c similarity index 100% rename from src/add-ons/kernel/generic/bios/x86emu/validate.c rename to src/libs/x86emu/validate.c From 25871c6895b536640b3d9f453e95219a54b84d20 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 4 Aug 2012 11:02:54 +0100 Subject: [PATCH 164/273] Removed Thread::fault_callback, no longer necessary now that vm86 is gone. --- headers/private/kernel/thread_types.h | 11 +-------- src/system/kernel/vm/vm.cpp | 34 ++++++++++++--------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 017da64352..78e893da3b 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -187,9 +187,6 @@ private: typedef int32 (*thread_entry_func)(thread_func, void *); -typedef bool (*page_fault_callback)(addr_t address, addr_t faultAddress, - bool isWrite); - namespace BKernel { @@ -477,13 +474,7 @@ struct Thread : TeamThreadIteratorEntry, KernelReferenceable { } msg; // write_sem/read_sem are protected by fLock when accessed by // others, the other fields are protected by write_sem/read_sem - union { - addr_t fault_handler; - page_fault_callback fault_callback; - // TODO: this is a temporary field used for the vm86 implementation - // and should be removed again when that one is moved into the - // kernel entirely. - }; + addr_t fault_handler; int32 page_faults_allowed; /* this field may only stay in debug builds in the future */ diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 7aaafabcdc..79eeb716e3 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -4130,25 +4130,21 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, addressSpace->ReadUnlock(); #endif - // TODO: the fault_callback is a temporary solution for vm86 - if (thread->fault_callback == NULL - || thread->fault_callback(address, faultAddress, isWrite)) { - // If the thread has a signal handler for SIGSEGV, we simply - // send it the signal. Otherwise we notify the user debugger - // first. - struct sigaction action; - if ((sigaction(SIGSEGV, NULL, &action) == 0 - && action.sa_handler != SIG_DFL - && action.sa_handler != SIG_IGN) - || user_debug_exception_occurred(B_SEGMENT_VIOLATION, - SIGSEGV)) { - Signal signal(SIGSEGV, - status == B_PERMISSION_DENIED - ? SEGV_ACCERR : SEGV_MAPERR, - EFAULT, thread->team->id); - signal.SetAddress((void*)address); - send_signal_to_thread(thread, signal, 0); - } + // If the thread has a signal handler for SIGSEGV, we simply + // send it the signal. Otherwise we notify the user debugger + // first. + struct sigaction action; + if ((sigaction(SIGSEGV, NULL, &action) == 0 + && action.sa_handler != SIG_DFL + && action.sa_handler != SIG_IGN) + || user_debug_exception_occurred(B_SEGMENT_VIOLATION, + SIGSEGV)) { + Signal signal(SIGSEGV, + status == B_PERMISSION_DENIED + ? SEGV_ACCERR : SEGV_MAPERR, + EFAULT, thread->team->id); + signal.SetAddress((void*)address); + send_signal_to_thread(thread, signal, 0); } } } From 57ab0395ad31761e27ef6d5aa3af68cc3e4d71b2 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 4 Aug 2012 16:10:00 +0100 Subject: [PATCH 165/273] 64-bit fixes for input_server. --- src/servers/input/AddOnManager.cpp | 2 +- src/servers/input/InputServer.cpp | 4 +-- src/servers/input/InputServerMethod.cpp | 10 +++--- src/servers/input/MethodMenuItem.cpp | 4 +-- src/servers/input/MethodMenuItem.h | 8 ++--- src/servers/input/MethodReplicant.cpp | 42 ++++++++++++------------- src/servers/input/MethodReplicant.h | 2 +- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/servers/input/AddOnManager.cpp b/src/servers/input/AddOnManager.cpp index 0d75e6a942..d5b8b47faf 100644 --- a/src/servers/input/AddOnManager.cpp +++ b/src/servers/input/AddOnManager.cpp @@ -440,7 +440,7 @@ AddOnManager::_UnregisterAddOn(BEntry& entry) gInputServer->SetMethodReplicant(NULL); } else if (method != NULL) { BMessage msg(IS_REMOVE_METHOD); - msg.AddInt32("cookie", (uint32)method); + msg.AddPointer("cookie", method); if (gInputServer->MethodReplicant()) gInputServer->MethodReplicant()->SendMessage(&msg); } diff --git a/src/servers/input/InputServer.cpp b/src/servers/input/InputServer.cpp index 685c548d4e..3fcc5b0cbf 100644 --- a/src/servers/input/InputServer.cpp +++ b/src/servers/input/InputServer.cpp @@ -625,8 +625,8 @@ void InputServer::HandleSetMethod(BMessage* message) { CALLED(); - uint32 cookie; - if (message->FindInt32("cookie", (int32*)&cookie) == B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) == B_OK) { BInputServerMethod *method = (BInputServerMethod*)cookie; PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, method)); SetActiveMethod(method); diff --git a/src/servers/input/InputServerMethod.cpp b/src/servers/input/InputServerMethod.cpp index 06adee4289..34fc75fd41 100644 --- a/src/servers/input/InputServerMethod.cpp +++ b/src/servers/input/InputServerMethod.cpp @@ -183,7 +183,7 @@ _BMethodAddOn_::SetName(const char* name) fName = strdup(name); BMessage msg(IS_UPDATE_NAME); - msg.AddInt32("cookie", (uint32)fMethod); + msg.AddPointer("cookie", fMethod); msg.AddString("name", name); if (((InputServer*)be_app)->MethodReplicant()) return ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg); @@ -203,7 +203,7 @@ _BMethodAddOn_::SetIcon(const uchar* icon) memset(fIcon, 0x1d, 16*16*1); BMessage msg(IS_UPDATE_ICON); - msg.AddInt32("cookie", (uint32)fMethod); + msg.AddPointer("cookie", fMethod); msg.AddData("icon", B_RAW_TYPE, icon, 16*16*1); if (((InputServer*)be_app)->MethodReplicant()) return ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg); @@ -220,7 +220,7 @@ _BMethodAddOn_::SetMenu(const BMenu *menu, const BMessenger &messenger) fMessenger = messenger; BMessage msg(IS_UPDATE_MENU); - msg.AddInt32("cookie", (uint32)fMethod); + msg.AddPointer("cookie", fMethod); BMessage menuMsg; if (menu) menu->Archive(&menuMsg); @@ -241,7 +241,7 @@ _BMethodAddOn_::MethodActivated(bool activate) PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, fMethod)); if (activate && ((InputServer*)be_app)->MethodReplicant()) { BMessage msg(IS_UPDATE_METHOD); - msg.AddInt32("cookie", (uint32)fMethod); + msg.AddPointer("cookie", fMethod); ((InputServer*)be_app)->MethodReplicant()->SendMessage(&msg); } return fMethod->MethodActivated(activate); @@ -255,7 +255,7 @@ _BMethodAddOn_::AddMethod() { PRINT(("%s cookie %p\n", __PRETTY_FUNCTION__, fMethod)); BMessage msg(IS_ADD_METHOD); - msg.AddInt32("cookie", (uint32)fMethod); + msg.AddPointer("cookie", fMethod); msg.AddString("name", fName); msg.AddData("icon", B_RAW_TYPE, fIcon, 16*16*1); if (((InputServer*)be_app)->MethodReplicant()) diff --git a/src/servers/input/MethodMenuItem.cpp b/src/servers/input/MethodMenuItem.cpp index daa66b0cc9..f6c7b2fe71 100644 --- a/src/servers/input/MethodMenuItem.cpp +++ b/src/servers/input/MethodMenuItem.cpp @@ -17,7 +17,7 @@ #include #include "MethodMenuItem.h" -MethodMenuItem::MethodMenuItem(int32 cookie, const char* name, const uchar* icon, BMenu *subMenu, BMessenger &messenger) +MethodMenuItem::MethodMenuItem(void *cookie, const char* name, const uchar* icon, BMenu *subMenu, BMessenger &messenger) : BMenuItem(subMenu), fIcon(BRect(0, 0, MENUITEM_ICON_SIZE - 1, MENUITEM_ICON_SIZE - 1), B_CMAP8), fCookie(cookie) @@ -28,7 +28,7 @@ MethodMenuItem::MethodMenuItem(int32 cookie, const char* name, const uchar* icon } -MethodMenuItem::MethodMenuItem(int32 cookie, const char* name, const uchar* icon) +MethodMenuItem::MethodMenuItem(void *cookie, const char* name, const uchar* icon) : BMenuItem(name, NULL), fIcon(BRect(0, 0, MENUITEM_ICON_SIZE - 1, MENUITEM_ICON_SIZE - 1), B_CMAP8), fCookie(cookie) diff --git a/src/servers/input/MethodMenuItem.h b/src/servers/input/MethodMenuItem.h index f2608dbdc3..25aa5c90dd 100644 --- a/src/servers/input/MethodMenuItem.h +++ b/src/servers/input/MethodMenuItem.h @@ -24,8 +24,8 @@ class MethodMenuItem : public BMenuItem { public: - MethodMenuItem(int32 cookie, const char *label, const uchar *icon, BMenu *subMenu, BMessenger &messenger); - MethodMenuItem(int32 cookie, const char *label, const uchar *icon); + MethodMenuItem(void *cookie, const char *label, const uchar *icon, BMenu *subMenu, BMessenger &messenger); + MethodMenuItem(void *cookie, const char *label, const uchar *icon); virtual ~MethodMenuItem(); @@ -38,10 +38,10 @@ class MethodMenuItem : public BMenuItem { void SetIcon(const uchar *icon); const uchar *Icon() { return(uchar *)fIcon.Bits(); }; - int32 Cookie() { return fCookie; }; + void *Cookie() { return fCookie; }; private: BBitmap fIcon; - int32 fCookie; + void *fCookie; BMessenger fMessenger; }; diff --git a/src/servers/input/MethodReplicant.cpp b/src/servers/input/MethodReplicant.cpp index 2a6c9dfc0e..2c99a5309d 100644 --- a/src/servers/input/MethodReplicant.cpp +++ b/src/servers/input/MethodReplicant.cpp @@ -194,7 +194,7 @@ MethodReplicant::MouseDown(BPoint point) if (dynamic_cast(item) != NULL) { BMessage msg(IS_SET_METHOD); - msg.AddInt32("cookie", ((MethodMenuItem*)item)->Cookie()); + msg.AddPointer("cookie", ((MethodMenuItem*)item)->Cookie()); BMessenger messenger(fSignature); messenger.SendMessage(&msg); } @@ -212,15 +212,15 @@ void MethodReplicant::UpdateMethod(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } MethodMenuItem* item = FindItemByCookie(cookie); if (item == NULL) { - fprintf(stderr, "can't find item with cookie %lx\n", cookie); + fprintf(stderr, "can't find item with cookie %p\n", cookie); return; } item->SetMarked(true); @@ -235,8 +235,8 @@ void MethodReplicant::UpdateMethodIcon(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } @@ -251,7 +251,7 @@ MethodReplicant::UpdateMethodIcon(BMessage* message) MethodMenuItem* item = FindItemByCookie(cookie); if (item == NULL) { - fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); + fprintf(stderr, "can't find item with cookie %p\n", cookie); return; } @@ -263,8 +263,8 @@ void MethodReplicant::UpdateMethodMenu(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } @@ -290,7 +290,7 @@ MethodReplicant::UpdateMethodMenu(BMessage* message) MethodMenuItem* item = FindItemByCookie(cookie); if (item == NULL) { - fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); + fprintf(stderr, "can't find item with cookie %p\n", cookie); return; } int32 index = fMenu.IndexOf(item); @@ -313,8 +313,8 @@ void MethodReplicant::UpdateMethodName(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } @@ -327,7 +327,7 @@ MethodReplicant::UpdateMethodName(BMessage* message) MethodMenuItem* item = FindItemByCookie(cookie); if (item == NULL) { - fprintf(stderr, "can't find item with cookie 0x%lx\n", cookie); + fprintf(stderr, "can't find item with cookie %p\n", cookie); return; } @@ -336,11 +336,11 @@ MethodReplicant::UpdateMethodName(BMessage* message) MethodMenuItem* -MethodReplicant::FindItemByCookie(int32 cookie) +MethodReplicant::FindItemByCookie(void* cookie) { for (int32 i = 0; i < fMenu.CountItems(); i++) { MethodMenuItem* item = (MethodMenuItem*)fMenu.ItemAt(i); - PRINT(("cookie : 0x%lx\n", item->Cookie())); + PRINT(("cookie : %p\n", item->Cookie())); if (item->Cookie() == cookie) return item; } @@ -353,8 +353,8 @@ void MethodReplicant::AddMethod(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } @@ -375,7 +375,7 @@ MethodReplicant::AddMethod(BMessage* message) MethodMenuItem* item = FindItemByCookie(cookie); if (item != NULL) { - fprintf(stderr, "item with cookie %lx already exists\n", cookie); + fprintf(stderr, "item with cookie %p already exists\n", cookie); return; } @@ -392,15 +392,15 @@ void MethodReplicant::RemoveMethod(BMessage* message) { CALLED(); - int32 cookie; - if (message->FindInt32("cookie", &cookie) != B_OK) { + void* cookie; + if (message->FindPointer("cookie", &cookie) != B_OK) { fprintf(stderr, "can't find cookie in message\n"); return; } MethodMenuItem* item = FindItemByCookie(cookie); if (item == NULL) { - fprintf(stderr, "can't find item with cookie %lx\n", cookie); + fprintf(stderr, "can't find item with cookie %p\n", cookie); return; } fMenu.RemoveItem(item); diff --git a/src/servers/input/MethodReplicant.h b/src/servers/input/MethodReplicant.h index b826fba17c..d40c704b98 100644 --- a/src/servers/input/MethodReplicant.h +++ b/src/servers/input/MethodReplicant.h @@ -57,7 +57,7 @@ class MethodReplicant : public BView { void UpdateMethodName(BMessage *); void AddMethod(BMessage *message); void RemoveMethod(BMessage *message); - MethodMenuItem *FindItemByCookie(int32 cookie); + MethodMenuItem *FindItemByCookie(void *cookie); }; #endif From 049d149cf760ee2c95b5f10032d39a9ade92525b Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sat, 4 Aug 2012 18:58:26 +0100 Subject: [PATCH 166/273] Handle 64-bit types correctly. --- src/kits/support/ByteOrder.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/kits/support/ByteOrder.cpp b/src/kits/support/ByteOrder.cpp index 649448741b..c009a5fe07 100644 --- a/src/kits/support/ByteOrder.cpp +++ b/src/kits/support/ByteOrder.cpp @@ -49,14 +49,15 @@ swap_data(type_code type, void *_data, size_t length, swap_action action) case B_FLOAT_TYPE: case B_INT32_TYPE: case B_UINT32_TYPE: - case B_SIZE_T_TYPE: - case B_SSIZE_T_TYPE: case B_TIME_TYPE: - case B_POINTER_TYPE: case B_RECT_TYPE: case B_POINT_TYPE: +#if B_HAIKU_32_BIT + case B_SIZE_T_TYPE: + case B_SSIZE_T_TYPE: + case B_POINTER_TYPE: +#endif { - // ToDo: some of these types may not be 32-bit on 64-bit platforms! uint32 *data = (uint32 *)_data; uint32 *end = (uint32 *)((addr_t)_data + length); @@ -72,6 +73,11 @@ swap_data(type_code type, void *_data, size_t length, swap_action action) case B_INT64_TYPE: case B_UINT64_TYPE: case B_OFF_T_TYPE: +#if B_HAIKU_64_BIT + case B_SIZE_T_TYPE: + case B_SSIZE_T_TYPE: + case B_POINTER_TYPE: +#endif { uint64 *data = (uint64 *)_data; uint64 *end = (uint64 *)((addr_t)_data + length); From f4294645358d2eeec007d93493f092581e9bb504 Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 5 Aug 2012 08:12:39 +0100 Subject: [PATCH 167/273] User symbol lookup works now on x86_64. --- src/system/kernel/elf.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/system/kernel/elf.cpp b/src/system/kernel/elf.cpp index 8c639e5f3f..2c068fc0b0 100644 --- a/src/system/kernel/elf.cpp +++ b/src/system/kernel/elf.cpp @@ -1338,8 +1338,6 @@ error1: // #pragma mark - userland symbol lookup -// TODO x86_64 -#ifndef __x86_64__ class UserSymbolLookup { public: static UserSymbolLookup& Default() @@ -1546,7 +1544,6 @@ UserSymbolLookup::_Read(const T* address, T& data) UserSymbolLookup UserSymbolLookup::sLookup; // doesn't need construction, but has an Init() method -#endif // #pragma mark - public kernel API @@ -1733,8 +1730,6 @@ elf_debug_lookup_user_symbol_address(Team* team, addr_t address, addr_t *_baseAddress, const char **_symbolName, const char **_imageName, bool *_exactMatch) { - // TODO x86_64 -#ifndef __x86_64__ if (team == NULL || team == team_get_kernel_team()) return B_BAD_VALUE; @@ -1745,9 +1740,6 @@ elf_debug_lookup_user_symbol_address(Team* team, addr_t address, return lookup.LookupSymbolAddress(address, _baseAddress, _symbolName, _imageName, _exactMatch); -#else - return B_ENTRY_NOT_FOUND; -#endif } From 3fed1a15f58e8d6fe6b492f3b94bb3625ffeddbd Mon Sep 17 00:00:00 2001 From: Alex Smith Date: Sun, 5 Aug 2012 08:46:30 +0100 Subject: [PATCH 168/273] Get app_server working on x86_64. With this commit, app_server now compiles and runs at boot! Nothing particularly interesting happens, just the blue background and a mouse pointer. Remote backends are broken and not compiled in, see #8834. Note that it won't be possible to build this quite yet, need to get the FreeType package uploaded. --- build/jam/Haiku64Image | 35 +++++++++--- build/jam/OptionalBuildFeatures | 4 +- headers/posix/netinet/in.h | 6 +- .../devices/wacom/MasterServerDevice.cpp | 2 +- src/kits/interface/ListView.cpp | 2 +- src/kits/network/libbind/irs/lcl_sv.cpp | 6 +- src/kits/network/libnetapi/init.cpp | 4 +- src/kits/shared/IconButton.cpp | 2 +- src/kits/translation/BitmapStream.cpp | 16 +++--- src/libs/linprog/Constraint.cpp | 2 +- src/libs/linprog/LinearSpec.cpp | 2 +- src/libs/linprog/Variable.cpp | 2 +- src/servers/app/AppServer.cpp | 10 ++-- src/servers/app/ClientMemoryAllocator.cpp | 16 +++--- src/servers/app/Desktop.cpp | 10 ++-- src/servers/app/DesktopSettings.cpp | 4 +- src/servers/app/DrawState.cpp | 12 ++-- src/servers/app/EventStream.cpp | 6 +- src/servers/app/IntPoint.cpp | 2 +- src/servers/app/IntRect.cpp | 3 +- src/servers/app/Jamfile | 7 ++- src/servers/app/MessageLooper.cpp | 4 +- src/servers/app/MultiLocker.cpp | 10 ++-- src/servers/app/MultiLocker.h | 4 +- src/servers/app/ScreenManager.cpp | 2 +- src/servers/app/ServerApp.cpp | 30 +++++----- src/servers/app/ServerBitmap.cpp | 5 +- src/servers/app/ServerFont.cpp | 2 +- src/servers/app/ServerWindow.cpp | 56 +++++++++---------- src/servers/app/View.cpp | 8 ++- .../app/drawing/AccelerantHWInterface.cpp | 2 +- .../app/drawing/Painter/AGGTextRenderer.cpp | 2 +- src/servers/app/font/FontCacheEntry.cpp | 2 +- src/servers/app/font/FontFamily.cpp | 2 +- src/servers/app/font/FontManager.cpp | 7 ++- src/servers/syslog_daemon/syslog_output.cpp | 6 +- 36 files changed, 167 insertions(+), 128 deletions(-) diff --git a/build/jam/Haiku64Image b/build/jam/Haiku64Image index 7f4f1b05a5..2139faeb50 100644 --- a/build/jam/Haiku64Image +++ b/build/jam/Haiku64Image @@ -40,13 +40,20 @@ SYSTEM_PREFERENCES = ; SYSTEM_DEMOS = ; -SYSTEM_LIBS = libbe.so libroot.so libroot-addon-icu.so +SYSTEM_LIBS = libbe.so libbnetapi.so libnetwork.so + libroot.so libroot-addon-icu.so + libtextencoding.so libtranslation.so $(HAIKU_SHARED_LIBSTDC++) $(HAIKU_SHARED_LIBSUPC++) + $(HAIKU_FREETYPE_CURRENT_LIB) ; PRIVATE_SYSTEM_LIBS = ; -SYSTEM_SERVERS = registrar ; +SYSTEM_SERVERS = app_server input_server registrar syslog_daemon ; + +SYSTEM_ADD_ONS_ACCELERANTS = vesa.accelerant ; + +SYSTEM_ADD_ONS_DRIVERS_GRAPHICS = vesa ; SYSTEM_ADD_ONS_BUS_MANAGERS = $(ATA_ONLY)ata pci ps2 isa scsi config_manager ; SYSTEM_ADD_ONS_FILE_SYSTEMS = bfs iso9660 attribute_overlay write_overlay ; @@ -79,6 +86,7 @@ AddNewDriversToHaikuImage disk scsi : scsi_cd scsi_disk ; # legacy drivers AddDriversToHaikuImage : console dprintf null random tty zero ; +AddDriversToHaikuImage graphics : $(SYSTEM_ADD_ONS_DRIVERS_GRAPHICS) ; AddDriversToHaikuImage input : ps2_hid ; # kernel @@ -88,6 +96,12 @@ AddFilesToHaikuImage system : kernel_$(TARGET_ARCH) ; AddLibrariesToHaikuHybridImage system lib : $(SYSTEM_LIBS) $(PRIVATE_SYSTEM_LIBS) ; +# libfreetype.so links to the current freetype lib +AddSymlinkToHaikuHybridImage system lib : $(HAIKU_FREETYPE_CURRENT_LIB:BS) + : $(HAIKU_FREETYPE_CURRENT_LINK) : : true ; +AddSymlinkToHaikuHybridImage system lib : $(HAIKU_FREETYPE_CURRENT_LINK) + : libfreetype.so : : true ; + # servers AddFilesToHaikuImage system servers : $(SYSTEM_SERVERS) ; @@ -139,11 +153,11 @@ local fortuneFiles = [ Glob $(HAIKU_TOP)/data/system/data/fortunes fortuneFiles = $(fortuneFiles:G=data!fortunes) ; AddFilesToHaikuImage system data fortunes : $(fortuneFiles) ; -#local fontDir = [ FDirName $(HAIKU_TOP) data system data fonts ] ; -#local psFonts = [ Glob $(fontDir)/psfonts : *.afm *.pfb ] ; -#local ttFonts = [ Glob $(fontDir)/ttfonts : *.ttf ] ; -#AddFilesToHaikuImage system data fonts psfonts : $(psFonts) ; -#AddFilesToHaikuImage system data fonts ttfonts : $(ttFonts) ; +local fontDir = [ FDirName $(HAIKU_TOP) data system data fonts ] ; +local psFonts = [ Glob $(fontDir)/psfonts : *.afm *.pfb ] ; +local ttFonts = [ Glob $(fontDir)/ttfonts : *.ttf ] ; +AddFilesToHaikuImage system data fonts psfonts : $(psFonts) ; +AddFilesToHaikuImage system data fonts ttfonts : $(ttFonts) ; local keymapFiles = [ Glob [ FDirName $(HAIKU_TOP) src data keymaps ] : *.keymap ] ; @@ -218,6 +232,13 @@ AddBootModuleSymlinksToHaikuImage bfs ; +# add-ons +AddFilesToHaikuImage system add-ons accelerants + : $(SYSTEM_ADD_ONS_ACCELERANTS) ; + +AddFilesToHaikuImage system add-ons input_server devices + :