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));
}