1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
/* -------------------------------------------
Copyright SoftwareLabs
------------------------------------------- */
#include <Builtins/ACPI/ACPIFactoryInterface.hxx>
#include <HALKit/AMD64/Processor.hpp>
#include <NewKit/KernelCheck.hpp>
#include <ArchKit/ArchKit.hpp>
#define kAPIC_ICR_Low 0x300
#define kAPIC_ICR_High 0x310
#define kAPIC_SIPI_Vector 0x00500
#define kAPIC_EIPI_Vector 0x00400
///////////////////////////////////////////////////////////////////////////////////////
//! NOTE: fGSI stands 'Field Global System Interrupt'
///////////////////////////////////////////////////////////////////////////////////////
namespace NewOS::HAL
{
constexpr Int32 kThreadAPIC = 0;
constexpr Int32 kThreadLAPIC = 1;
constexpr Int32 kThreadIOAPIC = 2;
constexpr Int32 kThreadAPIC64 = 3;
constexpr Int32 kThreadBoot = 4;
/*
*
* this is used to store info about the current running thread
* we use this struct to determine if we can use it, or mark it as used or on
* sleep.
*
*/
struct ProcessorInfoAMD64 final
{
Int32 ThreadType;
UIntPtr JumpAddress;
struct
{
UInt32 Code;
UInt32 Data;
UInt32 BSS;
} Selector;
};
STATIC voidPtr kApicMadt = nullptr;
STATIC const char* kApicSignature = "APIC";
/// @brief Multiple APIC Descriptor Table.
struct MadtType final : public SDT
{
struct MadtAddress final
{
Char RecordType;
Char RecordLen; // record length
UInt32 Address;
UInt32 Flags; // 1 = Dual Legacy PICs installed
} MadtRecords[];
};
struct MadtProcessorLocalApic final
{
Char AcpiProcessorId;
Char ApicId;
UInt32 Flags;
};
struct MadtIOApic final
{
Char ApicId;
Char Reserved;
UInt32 Address;
UInt32 SystemInterruptBase;
};
struct MadtInterruptSource final
{
Char BusSource;
Char IrqSource;
UInt32 GSI;
UInt16 Flags;
};
struct MadtInterruptNmi final
{
Char NmiSource;
Char Reserved;
UInt16 Flags;
UInt32 GSI;
};
struct MadtLocalApicAddressOverride final
{
UInt16 Resvered;
UIntPtr Address;
};
///////////////////////////////////////////////////////////////////////////////////////
STATIC MadtType* kApicInfoBlock = nullptr;
///////////////////////////////////////////////////////////////////////////////////////
/// @brief Send start IPI for CPU.
/// @param apicId
/// @param vector
/// @param targetAddress
/// @return
Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
{
NewOS::ke_dma_write(targetAddress, kAPIC_ICR_High, apicId << 24);
NewOS::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_SIPI_Vector | vector);
}
/// @brief Send end IPI for CPU.
/// @param apicId
/// @param vector
/// @param targetAddress
/// @return
Void hal_send_end_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
{
NewOS::ke_dma_write(targetAddress, kAPIC_ICR_High, apicId << 24);
NewOS::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_EIPI_Vector | vector);
}
Void hal_system_get_cores(voidPtr rsdPtr)
{
auto acpi = ACPIFactoryInterface(rsdPtr);
kApicMadt = acpi.Find(kApicSignature).Leak().Leak();
if (kApicMadt != nullptr)
{
auto madt = (SDT*)kApicMadt;
const UInt8* madt_end = (const UInt8*)madt + madt->Length;
const UInt8* entry_ptr = (const UInt8*)(madt + 1);
while (entry_ptr < madt_end)
{
const MadtType::MadtAddress* entry_header = (const MadtType::MadtAddress*)entry_ptr;
switch (entry_header->Flags)
{
case 0: {
const MadtProcessorLocalApic* local_apic = (const MadtProcessorLocalApic*)entry_ptr;
if (local_apic->Flags & 1)
{
// Processor is enabled
kcout << "Processor ID: %d, APIC ID: %d\n"
<< number(local_apic->AcpiProcessorId) << number(local_apic->ApicId);
}
break;
}
default:
break;
}
entry_ptr += entry_header->RecordLen;
}
while (true)
{
}
}
else
{
kcout << "New OS: APIC is not present! it is a vital component.\r";
ke_stop(RUNTIME_CHECK_FAILED);
}
}
} // namespace NewOS::HAL
///////////////////////////////////////////////////////////////////////////////////////
|