Skip to content

Commit 9d66069

Browse files
committed
Merge from x86-smp: implement SMP for both 32 and 64bit x86
A large pile of changes to the PC platform and x86 architecture that facilitate SMP support. Tested in both 64 and 32bit on qemu and real hardware all the way back through i486.
2 parents dd8210d + c80efdc commit 9d66069

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2690
-523
lines changed

.clang-tidy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Checks: >
33
-*,
44
bugprone-*,
55
-bugprone-easily-swappable-parameters,
6+
-bugprone-reserved-identifier,
67
78
clang-diagnostic-*,
89
-clang-diagnostic-unused-command-line-argument,
@@ -38,6 +39,7 @@ Checks: >
3839
-readability-implicit-bool-conversion,
3940
-readability-isolate-declaration,
4041
-readability-magic-numbers,
42+
-readability-math-missing-parentheses,
4143
-readability-named-parameter,
4244
-readability-qualified-auto,
4345
-readability-uppercase-literal-suffix,

arch/arm64/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ __SECTION(".bss.prebss.translation_table");
3434
/* the base TCR flags, computed from early init code in start.S */
3535
uint64_t arm64_mmu_tcr_flags __SECTION(".bss.prebss.tcr_flags");
3636

37-
static inline bool is_valid_vaddr(arch_aspace_t *aspace, vaddr_t vaddr) {
37+
static inline bool is_valid_vaddr(const arch_aspace_t *aspace, vaddr_t vaddr) {
3838
return (vaddr >= aspace->base && vaddr <= aspace->base + aspace->size - 1);
3939
}
4040

arch/test/mmu.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
#include <lib/unittest.h>
1616
#include <kernel/vm.h>
1717

18-
static bool create_user_aspace(void) {
18+
namespace {
19+
20+
bool create_user_aspace() {
1921
BEGIN_TEST;
2022

2123
if (arch_mmu_supports_user_aspaces()) {
@@ -34,7 +36,7 @@ static bool create_user_aspace(void) {
3436
END_TEST;
3537
}
3638

37-
static bool map_user_pages(void) {
39+
bool map_user_pages() {
3840
BEGIN_TEST;
3941

4042
if (arch_mmu_supports_user_aspaces()) {
@@ -89,7 +91,7 @@ static bool map_user_pages(void) {
8991
END_TEST;
9092
}
9193

92-
static bool map_region_query_result(vmm_aspace_t *aspace, uint arch_flags) {
94+
bool map_region_query_result(vmm_aspace_t *aspace, uint arch_flags) {
9395
BEGIN_TEST;
9496
void *ptr = NULL;
9597

@@ -109,10 +111,17 @@ static bool map_region_query_result(vmm_aspace_t *aspace, uint arch_flags) {
109111
// free this region we made
110112
EXPECT_EQ(NO_ERROR, vmm_free_region(aspace, (vaddr_t)ptr), "free region");
111113

114+
// query that the page is not there anymore
115+
{
116+
paddr_t pa = 0;
117+
uint flags = ~arch_flags;
118+
EXPECT_EQ(ERR_NOT_FOUND, arch_mmu_query(&aspace->arch_aspace, (vaddr_t)ptr, &pa, &flags), "arch_query");
119+
}
120+
112121
END_TEST;
113122
}
114123

115-
static bool map_region_expect_failure(vmm_aspace_t *aspace, uint arch_flags, int expected_error) {
124+
bool map_region_expect_failure(vmm_aspace_t *aspace, uint arch_flags, int expected_error) {
116125
BEGIN_TEST;
117126
void *ptr = NULL;
118127

@@ -123,7 +132,7 @@ static bool map_region_expect_failure(vmm_aspace_t *aspace, uint arch_flags, int
123132
END_TEST;
124133
}
125134

126-
static bool map_query_pages(void) {
135+
bool map_query_pages() {
127136
BEGIN_TEST;
128137

129138
vmm_aspace_t *kaspace = vmm_get_kernel_aspace();
@@ -153,9 +162,12 @@ static bool map_query_pages(void) {
153162
END_TEST;
154163
}
155164

156-
static bool context_switch(void) {
165+
bool context_switch() {
157166
BEGIN_TEST;
158167

168+
// create a user space, map a page or two and access it
169+
// NOTE: this assumes that kernel code can directly access user space, which isn't necessarily true
170+
// on all architectures. See SMAP on x86, PAN on ARM, and SUM on RISC-V.
159171
if (arch_mmu_supports_user_aspaces()) {
160172
arch_aspace_t as;
161173
status_t err = arch_mmu_init_aspace(&as, USER_ASPACE_BASE, USER_ASPACE_SIZE, 0);
@@ -218,4 +230,6 @@ RUN_TEST(map_query_pages);
218230
RUN_TEST(context_switch);
219231
END_TEST_CASE(arch_mmu_tests)
220232

233+
} // namespace
234+
221235
#endif // ARCH_HAS_MMU

arch/x86/32/exceptions.S

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ LOCAL_FUNCTION(interrupt_common)
4545
pushl %ds
4646
pusha /* save general purpose registers */
4747
movl $DATA_SELECTOR, %eax /* put known good value in segment registers */
48-
movl %eax, %gs
48+
// do not reset %gs, as it is used by the kernel
49+
// TODO: when dealing with user space, we need to reset %gs here
4950
movl %eax, %fs
5051
movl %eax, %es
5152
movl %eax, %ds
@@ -61,8 +62,7 @@ LOCAL_FUNCTION(interrupt_common)
6162
popl %ds /* restore segment registers */
6263
popl %es
6364
popl %fs
64-
popl %gs
65-
addl $8, %esp /* drop exception number and error code */
65+
addl $12, %esp /* drop gs, exception number, and error code */
6666
iret
6767
END_FUNCTION(interrupt_common)
6868

@@ -83,8 +83,6 @@ FUNCTION(setup_idt)
8383

8484
loop .Lloop
8585

86-
lidt _idtr
87-
8886
ret
8987
END_FUNCTION(setup_idt)
9088

arch/x86/32/gdt.S

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright (c) 2009 Corey Tabaka
3+
* Copyright (c) 2015 Intel Corporation
4+
* Copyright (c) 2016 Travis Geiselbrecht
5+
*
6+
* Use of this source code is governed by a MIT-style
7+
* license that can be found in the LICENSE file or at
8+
* https://opensource.org/licenses/MIT
9+
*/
10+
#include <lk/asm.h>
11+
#include <arch/x86/descriptor.h>
12+
13+
#define PHYS_LOAD_ADDRESS (MEMBASE + KERNEL_LOAD_OFFSET)
14+
#define PHYS_ADDR_DELTA (KERNEL_BASE + KERNEL_LOAD_OFFSET - PHYS_LOAD_ADDRESS)
15+
#define PHYS(x) ((x) - PHYS_ADDR_DELTA)
16+
17+
.section .rodata
18+
19+
.balign 8
20+
DATA(_gdtr_phys)
21+
.short _gdt_end - _gdt - 1
22+
.int PHYS(_gdt)
23+
END_DATA(_gdtr_phys)
24+
25+
.balign 8
26+
DATA(_gdtr)
27+
.short _gdt_end - _gdt - 1
28+
.int _gdt
29+
END_DATA(_gdtr)
30+
31+
32+
// 32bit GDT, laid out in a specific way due to requirements by the SYSENTER/SYSEXIT and
33+
// SYSCALL/SYSRET instructions:
34+
//
35+
// CODE32 <- IA32_SYSENTER_CS, IA32_STAR.SYSCALL_CS
36+
// DATA
37+
// UCODE32 <- IA32_STAR.SYSRET_CS
38+
// UDATA
39+
.data
40+
.balign 8
41+
DATA(_gdt)
42+
.int 0
43+
.int 0
44+
45+
/* ring 0 code 32bit (for bootstrapping into 64bit) */
46+
.short 0xffff /* limit 15:00 */
47+
.short 0x0000 /* base 15:00 */
48+
.byte 0x00 /* base 23:16 */
49+
.byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
50+
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
51+
.byte 0x0 /* base 31:24 */
52+
53+
/* ring 0 data 32bit */
54+
.short 0xffff /* limit 15:00 */
55+
.short 0x0000 /* base 15:00 */
56+
.byte 0x00 /* base 23:16 */
57+
.byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
58+
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
59+
.byte 0x0 /* base 31:24 */
60+
61+
/* ring 3 code 32bit */
62+
.short 0xffff /* limit 15:00 */
63+
.short 0x0000 /* base 15:00 */
64+
.byte 0x00 /* base 23:16 */
65+
.byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
66+
.byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
67+
.byte 0x0 /* base 31:24 */
68+
69+
/* ring 3 data 32bit */
70+
.short 0xffff /* limit 15:00 */
71+
.short 0x0000 /* base 15:00 */
72+
.byte 0x00 /* base 23:16 */
73+
.byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
74+
.byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
75+
.byte 0x0 /* base 31:24 */
76+
77+
/* per-cpu TSS descriptor */
78+
.set i, 1
79+
.rept SMP_MAX_CPUS
80+
.short 0 /* limit 15:00 */
81+
.short 0 /* base 15:00 */
82+
.byte 0 /* base 23:16 */
83+
.byte 0x89 /* P(1) DPL(00) S(0) TYPE(9) */
84+
.byte 0x80 /* G(1) D/B(0) L(0) AVL(0) limit 19:16 */
85+
.byte 0 /* base 31:24 */
86+
.set i, i+1
87+
.endr
88+
89+
/* per-cpu GS descriptor for x86-32 */
90+
.set i, 1
91+
.rept SMP_MAX_CPUS
92+
.int 0 /* filled in by C code later */
93+
.int 0
94+
.set i, i+1
95+
.endr
96+
97+
END_DATA(_gdt)
98+
99+
DATA(_gdt_end)
100+

0 commit comments

Comments
 (0)