[haiku-commits] haiku: hrev51940 - src/system/kernel/arch/x86/64 headers/private/kernel/arch/x86/64 headers/private/kernel/arch/x86 headers/private/kernel headers/private/kernel/arch/x86/32

  • From: Jérôme Duval <jerome.duval@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 15 May 2018 06:27:05 -0400 (EDT)

hrev51940 adds 1 changeset to branch 'master'
old head: 6692e4c87f5ae79861af13137bfe4da953196f58
new head: 27b32ee02c3ba1278e17c41fdd2c1768062ee99e
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=27b32ee02c3b+%5E6692e4c87f5a

----------------------------------------------------------------------------

27b32ee02c3b: kernel/x86_64: adjust descriptors tables for compatibility mode.
  
  * also adjust BOOT_GDT_SEGMENT_COUNT for x86, the definition is used by the
  boot loader.
  * add some 32-bit definitions.
  * add a UserTLSDescriptor class, this will be used by 32-bit threads.
  
  Change-Id: I5b1d978969a1ce97091a16c9ec2ad7c0ca831656

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev51940
Commit:      27b32ee02c3ba1278e17c41fdd2c1768062ee99e
URL:         https://git.haiku-os.org/haiku/commit/?id=27b32ee02c3b
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Thu May  3 17:54:33 2018 UTC

----------------------------------------------------------------------------

7 files changed, 81 insertions(+), 17 deletions(-)
headers/private/kernel/arch/x86/32/descriptors.h |  2 +-
headers/private/kernel/arch/x86/64/descriptors.h | 13 +++--
headers/private/kernel/arch/x86/arch_kernel.h    | 12 +++++
headers/private/kernel/thread_types.h            |  5 +-
headers/private/system/tls.h                     |  1 +
src/system/kernel/arch/x86/64/descriptors.cpp    | 57 +++++++++++++++++---
src/system/kernel/arch/x86/64/syscalls.cpp       |  8 +--

----------------------------------------------------------------------------

diff --git a/headers/private/kernel/arch/x86/32/descriptors.h 
b/headers/private/kernel/arch/x86/32/descriptors.h
index 535c6a1d5f..2aa3941a71 100644
--- a/headers/private/kernel/arch/x86/32/descriptors.h
+++ b/headers/private/kernel/arch/x86/32/descriptors.h
@@ -16,7 +16,7 @@
 #define USER_CODE_SEGMENT                      3
 #define USER_DATA_SEGMENT                      4
 
-#define BOOT_GDT_SEGMENT_COUNT         (USER_DATA_SEGMENT + 1)
+#define BOOT_GDT_SEGMENT_COUNT         (USER_DATA_SEGMENT + 2) // match x86_64
 
 #define APM_CODE32_SEGMENT                     5
 #define APM_CODE16_SEGMENT                     6
diff --git a/headers/private/kernel/arch/x86/64/descriptors.h 
b/headers/private/kernel/arch/x86/64/descriptors.h
index e359741d63..82a44e277e 100644
--- a/headers/private/kernel/arch/x86/64/descriptors.h
+++ b/headers/private/kernel/arch/x86/64/descriptors.h
@@ -10,16 +10,18 @@
 // Note that the ordering of these is important to SYSCALL/SYSRET.
 #define KERNEL_CODE_SEGMENT            1
 #define KERNEL_DATA_SEGMENT            2
-#define USER_DATA_SEGMENT              3
-#define USER_CODE_SEGMENT              4
+#define USER32_CODE_SEGMENT            3
+#define USER_DATA_SEGMENT              4
+#define USER_CODE_SEGMENT              5
 
 #define BOOT_GDT_SEGMENT_COUNT (USER_CODE_SEGMENT + 1)
 
 #define KERNEL_CODE_SELECTOR   ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL)
 #define KERNEL_DATA_SELECTOR   ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL)
 
-#define USER_CODE_SELECTOR     ((USER_CODE_SEGMENT << 3) | DPL_USER)
-#define USER_DATA_SELECTOR     ((USER_DATA_SEGMENT << 3) | DPL_USER)
+#define USER32_CODE_SELECTOR   ((USER32_CODE_SEGMENT << 3) | DPL_USER)
+#define USER_CODE_SELECTOR             ((USER_CODE_SEGMENT << 3) | DPL_USER)
+#define USER_DATA_SELECTOR             ((USER_DATA_SEGMENT << 3) | DPL_USER)
 
 
 #ifndef _ASSEMBLER
@@ -90,6 +92,9 @@ set_segment_descriptor(segment_descriptor* desc, uint8 type, 
uint8 dpl)
 }
 
 
+unsigned x86_64_set_user_tls_segment_base(int cpu, addr_t base);
+
+
 #endif /* _ASSEMBLER */
 
 #endif /* _KERNEL_ARCH_X86_64_DESCRIPTORS_H */
diff --git a/headers/private/kernel/arch/x86/arch_kernel.h 
b/headers/private/kernel/arch/x86/arch_kernel.h
index 3effe2da51..931176bcc6 100644
--- a/headers/private/kernel/arch/x86/arch_kernel.h
+++ b/headers/private/kernel/arch/x86/arch_kernel.h
@@ -54,6 +54,18 @@
 #define USER_STACK_REGION              0x7f0000000000
 #define USER_STACK_REGION_SIZE ((USER_TOP - USER_STACK_REGION) + 1)
 
+#ifdef _COMPAT_MODE
+
+#define USER32_SIZE                            0x100000000
+#define USER32_TOP                             (USER_BASE + (USER32_SIZE - 1))
+
+#define KERNEL_USER32_DATA_BASE        0x60000000
+
+#define USER32_STACK_REGION            0x70000000
+#define USER32_STACK_REGION_SIZE       ((USER32_TOP - USER32_STACK_REGION) + 1)
+
+#endif // _COMPAT_MODE
+
 
 #else  // __x86_64__
 
diff --git a/headers/private/kernel/thread_types.h 
b/headers/private/kernel/thread_types.h
index 720a221c17..33a535c708 100644
--- a/headers/private/kernel/thread_types.h
+++ b/headers/private/kernel/thread_types.h
@@ -837,6 +837,9 @@ using BKernel::ProcessGroupList;
 #define        THREAD_FLAGS_TRAP_FOR_CORE_DUMP         0x1000
        // core dump in progress; the thread shall not exit the kernel to 
userland,
        // but shall invoke core_dump_trap_thread() instead.
-
+#ifdef _COMPAT_MODE
+#define        THREAD_FLAGS_COMPAT_MODE                        0x2000
+       // the thread runs a compatibility mode (for instance IA32 on x86_64).
+#endif
 
 #endif /* _KERNEL_THREAD_TYPES_H */
diff --git a/headers/private/system/tls.h b/headers/private/system/tls.h
index 751332e33f..f173755c56 100644
--- a/headers/private/system/tls.h
+++ b/headers/private/system/tls.h
@@ -10,6 +10,7 @@
 
 
 #define TLS_SIZE (TLS_MAX_KEYS * sizeof(void *))
+#define TLS_COMPAT_SIZE (TLS_MAX_KEYS * sizeof(uint32))
 
 enum {
        TLS_BASE_ADDRESS_SLOT = 0,
diff --git a/src/system/kernel/arch/x86/64/descriptors.cpp 
b/src/system/kernel/arch/x86/64/descriptors.cpp
index f4fee71dd3..3e516f0134 100644
--- a/src/system/kernel/arch/x86/64/descriptors.cpp
+++ b/src/system/kernel/arch/x86/64/descriptors.cpp
@@ -9,6 +9,7 @@
 
 #include <boot/kernel_args.h>
 #include <cpu.h>
+#include <tls.h>
 #include <vm/vm.h>
 #include <vm/vm_priv.h>
 
@@ -41,7 +42,8 @@ class Descriptor {
 public:
        constexpr                               Descriptor();
        inline                                  Descriptor(uint32_t first, 
uint32_t second);
-       constexpr                               Descriptor(DescriptorType type, 
bool kernelOnly);
+       constexpr                               Descriptor(DescriptorType type, 
bool kernelOnly,
+                                                               bool compatMode 
= false);
 
 protected:
        union {
@@ -77,6 +79,15 @@ private:
                        Descriptor                      fSecond;
 };
 
+
+class UserTLSDescriptor : public Descriptor {
+public:
+       inline                                          
UserTLSDescriptor(uintptr_t base, size_t limit);
+
+                       const Descriptor&       GetDescriptor() const   { 
return *this; }
+};
+
+
 class GlobalDescriptorTable {
 public:
        constexpr                                               
GlobalDescriptorTable();
@@ -85,10 +96,12 @@ public:
 
                        unsigned                                SetTSS(unsigned 
cpu,
                                                                                
const TSSDescriptor& tss);
+                       unsigned                                
SetUserTLS(unsigned cpu,
+                                                                               
addr_t base, size_t limit);
 private:
-       static constexpr        unsigned        kFirstTSS = 5;
+       static constexpr        unsigned        kFirstTSS = 6;
        static constexpr        unsigned        kDescriptorCount
-                                                                               
= kFirstTSS + SMP_MAX_CPUS * 2;
+                                                                               
= kFirstTSS + SMP_MAX_CPUS * 3;
 
        alignas(uint64_t)       Descriptor      fTable[kDescriptorCount];
 };
@@ -172,7 +185,7 @@ Descriptor::Descriptor(uint32_t first, uint32_t second)
 
 
 constexpr
-Descriptor::Descriptor(DescriptorType type, bool kernelOnly)
+Descriptor::Descriptor(DescriptorType type, bool kernelOnly, bool compatMode)
        :
        fLimit0(-1),
        fBase0(0),
@@ -182,8 +195,8 @@ Descriptor::Descriptor(DescriptorType type, bool kernelOnly)
        fPresent(1),
        fLimit1(0xf),
        fUnused(0),
-       fLong(is_code_segment(type) ? 1 : 0),
-       fDB(is_code_segment(type) ? 0 : 1),
+       fLong(is_code_segment(type) && !compatMode ? 1 : 0),
+       fDB(is_code_segment(type) && !compatMode ? 0 : 1),
        fGranularity(1),
        fBase1(0)
 {
@@ -210,6 +223,16 @@ TSSDescriptor::LoadTSS(unsigned index)
 }
 
 
+UserTLSDescriptor::UserTLSDescriptor(uintptr_t base, size_t limit)
+       : Descriptor(DescriptorType::DataWritable, false)
+{
+       fLimit0 = static_cast<uint16_t>(limit);
+       fBase0 = base & 0xffffff;
+       fLimit1 = (limit >> 16) & 0xf;
+       fBase1 = static_cast<uint8_t>(base >> 24);
+}
+
+
 constexpr
 GlobalDescriptorTable::GlobalDescriptorTable()
        :
@@ -217,6 +240,7 @@ GlobalDescriptorTable::GlobalDescriptorTable()
                Descriptor(),
                Descriptor(DescriptorType::CodeExecuteOnly, true),
                Descriptor(DescriptorType::DataWritable, true),
+               Descriptor(DescriptorType::CodeExecuteOnly, false, true),
                Descriptor(DescriptorType::DataWritable, false),
                Descriptor(DescriptorType::CodeExecuteOnly, false),
        }
@@ -244,7 +268,7 @@ GlobalDescriptorTable::Load() const
 unsigned
 GlobalDescriptorTable::SetTSS(unsigned cpu, const TSSDescriptor& tss)
 {
-       auto index = kFirstTSS + cpu * 2;
+       auto index = kFirstTSS + cpu * 3;
        ASSERT(index + 1 < kDescriptorCount);
        fTable[index] = tss.GetLower();
        fTable[index + 1] = tss.GetUpper();
@@ -252,6 +276,17 @@ GlobalDescriptorTable::SetTSS(unsigned cpu, const 
TSSDescriptor& tss)
 }
 
 
+unsigned
+GlobalDescriptorTable::SetUserTLS(unsigned cpu, uintptr_t base, size_t limit)
+{
+       auto index = kFirstTSS + cpu * 3 + 2;
+       ASSERT(index + 1 < kDescriptorCount);
+       UserTLSDescriptor desc(base, limit);
+       fTable[index] = desc.GetDescriptor();
+       return index;
+}
+
+
 constexpr
 InterruptDescriptor::InterruptDescriptor(uintptr_t isr, unsigned ist,
        bool kernelOnly)
@@ -361,6 +396,8 @@ x86_descriptors_preboot_init_percpu(kernel_args* args, int 
cpu)
                        TSSDescriptor(uintptr_t(&gCPU[cpu].arch.tss), 
sizeof(struct tss)));
        TSSDescriptor::LoadTSS(tssIndex);
 
+       sGDT.SetUserTLS(cpu, 0, TLS_COMPAT_SIZE);
+
        new(&sIDT) InterruptDescriptorTable;
        sIDT.Load();
 }
@@ -399,3 +436,9 @@ x86_descriptors_init(kernel_args* args)
        table[19] = x86_unexpected_exception;   // SIMD Floating-Point 
Exception (#XF)
 }
 
+
+unsigned
+x86_64_set_user_tls_segment_base(int cpu, addr_t base)
+{
+       return sGDT.SetUserTLS(cpu, base, TLS_COMPAT_SIZE);
+}
diff --git a/src/system/kernel/arch/x86/64/syscalls.cpp 
b/src/system/kernel/arch/x86/64/syscalls.cpp
index 7bcfeda5ae..907dd4989d 100644
--- a/src/system/kernel/arch/x86/64/syscalls.cpp
+++ b/src/system/kernel/arch/x86/64/syscalls.cpp
@@ -42,10 +42,10 @@ init_syscall_registers(void* dummy, int cpuNum)
        // From this we get:
        //  - Entry CS  = KERNEL_CODE_SELECTOR
        //  - Entry SS  = KERNEL_CODE_SELECTOR + 8  = KERNEL_DATA_SELECTOR
-       //  - Return CS = KERNEL_DATA_SELECTOR + 16 = USER_CODE_SELECTOR
-       //  - Return SS = KERNEL_DATA_SELECTOR + 8  = USER_DATA_SLECTORG
-       x86_write_msr(IA32_MSR_STAR, ((uint64)(KERNEL_DATA_SELECTOR | 3) << 48)
-               | ((uint64)KERNEL_CODE_SELECTOR << 32));
+       //  - Return CS = USER32_CODE_SELECTOR + 16 = USER_CODE_SELECTOR
+       //  - Return SS = USER32_CODE_SELECTOR + 8  = USER_DATA_SELECTOR
+       x86_write_msr(IA32_MSR_STAR, ((uint64)(USER32_CODE_SELECTOR) << 48)
+               | ((uint64)(KERNEL_CODE_SELECTOR) << 32));
 }
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev51940 - src/system/kernel/arch/x86/64 headers/private/kernel/arch/x86/64 headers/private/kernel/arch/x86 headers/private/kernel headers/private/kernel/arch/x86/32 - Jérôme Duval