Skip to content

Commit 1391c28

Browse files
committed
kernel
1 parent 84ec37a commit 1391c28

6 files changed

Lines changed: 164 additions & 29 deletions

File tree

include/kernel.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,36 @@ uint32_t acpi_rsdp_addr(void);
2121
uint32_t acpi_rsdt_addr(void);
2222
uint32_t acpi_rsdt_entries(void);
2323
uint32_t acpi_rsdt_entry(uint32_t index);
24+
uint32_t acpi_find_table(const char* signature);
25+
26+
typedef struct {
27+
uint8_t signature[4];
28+
uint32_t length;
29+
uint8_t revision;
30+
uint8_t checksum;
31+
uint8_t oemid[6];
32+
uint8_t oem_table_id[8];
33+
uint32_t oem_revision;
34+
uint32_t creator_id;
35+
uint32_t creator_revision;
36+
} acpi_sdt_header_t;
37+
38+
typedef struct {
39+
acpi_sdt_header_t header;
40+
uint32_t local_apic_address;
41+
uint32_t flags;
42+
} __attribute__((packed)) acpi_madt_t;
43+
44+
typedef struct {
45+
uint8_t type;
46+
uint8_t length;
47+
} __attribute__((packed)) acpi_madt_entry_t;
48+
49+
typedef struct {
50+
acpi_madt_entry_t header;
51+
uint8_t processor_id;
52+
uint8_t apic_id;
53+
uint32_t flags;
54+
} __attribute__((packed)) acpi_madt_local_apic_t;
2455

2556
#endif

include/ports.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@ static inline unsigned char inb(unsigned short port) {
1111
return ret;
1212
}
1313

14+
static inline void outw(unsigned short port, unsigned short value) {
15+
asm volatile("outw %0, %1" : : "a"(value), "Nd"(port));
16+
}
17+
18+
static inline unsigned short inw(unsigned short port) {
19+
unsigned short ret;
20+
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
21+
return ret;
22+
}
23+
24+
static inline void outl(unsigned short port, unsigned int value) {
25+
asm volatile("outl %0, %1" : : "a"(value), "Nd"(port));
26+
}
27+
28+
static inline unsigned int inl(unsigned short port) {
29+
unsigned int ret;
30+
asm volatile("inl %1, %0" : "=a"(ret) : "Nd"(port));
31+
return ret;
32+
}
33+
1434
static inline void io_wait(void) {
1535
asm volatile("outb %%al, $0x80" : : "a"(0));
1636
}

src/cpu/smp_rally.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
11
#include "smp_rally.h"
2+
#include "kernel.h"
23
#include "types.h"
4+
#include "util.h"
35

46
static uint32_t cpu_count = 1;
57
static uint32_t online_mask = 1;
68

79
void smp_rally_init(void) {
810
cpu_count = 1;
911
online_mask = 1;
12+
13+
uint32_t madt_addr = acpi_find_table("APIC");
14+
if (!madt_addr) {
15+
return;
16+
}
17+
18+
acpi_madt_t* madt = (acpi_madt_t*)madt_addr;
19+
uint32_t length = madt->header.length;
20+
uint32_t current = madt_addr + sizeof(acpi_madt_t);
21+
uint32_t end = madt_addr + length;
22+
23+
cpu_count = 0;
24+
while (current < end) {
25+
acpi_madt_entry_t* entry = (acpi_madt_entry_t*)current;
26+
if (entry->length == 0) break; // Prevent infinite loop
27+
28+
if (entry->type == 0) { // Local APIC
29+
acpi_madt_local_apic_t* lapic = (acpi_madt_local_apic_t*)current;
30+
if (lapic->flags & 1) { // Enabled
31+
cpu_count++;
32+
}
33+
}
34+
current += entry->length;
35+
}
36+
37+
if (cpu_count == 0) cpu_count = 1;
38+
online_mask = 1;
1039
}
1140

1241
uint32_t smp_rally_cpu_count(void) {

src/kernel.c

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -165,35 +165,15 @@ typedef struct {
165165
uint32_t rsdt_address;
166166
} acpi_rsdp_t;
167167

168-
typedef struct {
169-
uint8_t signature[4];
170-
uint32_t length;
171-
uint8_t revision;
172-
uint8_t checksum;
173-
uint8_t oemid[6];
174-
uint8_t oem_table_id[8];
175-
uint32_t oem_revision;
176-
uint32_t creator_id;
177-
uint32_t creator_revision;
178-
} acpi_sdt_header_t;
179-
180168
static uint32_t acpi_rsdp_phys = 0;
181169
static uint32_t acpi_rsdt_phys = 0;
182170
static uint32_t acpi_rsdt_count = 0;
183171

184172
uint32_t pci_config_read(uint8_t bus, uint8_t slot, uint8_t func, uint8_t offset) {
185173
uint32_t address = (uint32_t)(0x80000000u | ((uint32_t)bus << 16)
186174
| ((uint32_t)slot << 11) | ((uint32_t)func << 8) | (offset & 0xFC));
187-
outb(0xCF8, (uint8_t)(address & 0xFF));
188-
outb(0xCF8 + 1, (uint8_t)((address >> 8) & 0xFF));
189-
outb(0xCF8 + 2, (uint8_t)((address >> 16) & 0xFF));
190-
outb(0xCF8 + 3, (uint8_t)((address >> 24) & 0xFF));
191-
uint32_t data = 0;
192-
data |= (uint32_t)inb(0xCFC);
193-
data |= (uint32_t)inb(0xCFC + 1) << 8;
194-
data |= (uint32_t)inb(0xCFC + 2) << 16;
195-
data |= (uint32_t)inb(0xCFC + 3) << 24;
196-
return data;
175+
outl(0xCF8, address);
176+
return inl(0xCFC);
197177
}
198178

199179
uint32_t pci_scan_bus(void) {
@@ -336,6 +316,19 @@ uint32_t acpi_rsdt_entry(uint32_t index) {
336316
return entries[index];
337317
}
338318

319+
uint32_t acpi_find_table(const char* signature) {
320+
if (!acpi_rsdt_phys) return 0;
321+
for (uint32_t i = 0; i < acpi_rsdt_count; ++i) {
322+
uint32_t entry = acpi_rsdt_entry(i);
323+
if (!entry) continue;
324+
const acpi_sdt_header_t* hdr = (const acpi_sdt_header_t*)entry;
325+
if (memcmp(hdr->signature, signature, 4) == 0) {
326+
return entry;
327+
}
328+
}
329+
return 0;
330+
}
331+
339332
static void task_a(void) {
340333
const char spin[] = "|/-\\";
341334
uint32_t i = 0;

src/kernel/sched.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "sched.h"
33
#include "secure_caps.h"
44
#include "signal.h"
5+
#include "smp_rally.h"
56
#include "timer.h"
67
#include "types.h"
78
#include "vm_space.h"
@@ -101,10 +102,11 @@ static void list_append(process_t* proc) {
101102
static void enqueue_task(process_t* proc) {
102103
uint32_t best_cpu = 0;
103104
uint32_t min_count = 0xFFFFFFFF;
105+
uint32_t online = smp_rally_online_mask();
104106

105-
// Find best CPU
107+
// Find best CPU among online ones in mask
106108
for (uint32_t i = 0; i < MAX_CPUS; i++) {
107-
if ((proc->cpu_mask & (1 << i)) && runqueues[i].count < min_count) {
109+
if ((online & (1 << i)) && (proc->cpu_mask & (1 << i)) && runqueues[i].count < min_count) {
108110
min_count = runqueues[i].count;
109111
best_cpu = i;
110112
}
@@ -288,7 +290,7 @@ static process_t* process_create_ex(void (*entry)(void), uint32_t* page_director
288290
proc->time_slice = default_time_slice;
289291
proc->time_remaining = default_time_slice;
290292
proc->sched_class = SCHED_CLASS_CFS;
291-
proc->cpu_mask = 1;
293+
proc->cpu_mask = 0xFFFFFFFF;
292294
proc->cgroup_share = 1024;
293295

294296
proc->parent_pid = proc->pid;
@@ -513,9 +515,10 @@ void scheduler_balance_load(void) {
513515

514516
uint32_t busiest_cpu = this_cpu;
515517
uint32_t max_count = 0;
518+
uint32_t online = smp_rally_online_mask();
516519

517520
for (uint32_t i = 0; i < MAX_CPUS; i++) {
518-
if (runqueues[i].count > max_count) {
521+
if ((online & (1 << i)) && runqueues[i].count > max_count) {
519522
max_count = runqueues[i].count;
520523
busiest_cpu = i;
521524
}
@@ -692,7 +695,7 @@ process_t* switch_task(registers_t* saved_stack, process_t** previous) {
692695
int switch_needed = 0;
693696
if (best) {
694697
// Priority class overrides
695-
if (best->sched_class < current->sched_class) switch_needed = 1;
698+
if (best->sched_class > current->sched_class) switch_needed = 1;
696699
else if (best->sched_class == current->sched_class) {
697700
if (best->sched_class == SCHED_CLASS_RT && best_prio > current_prio) switch_needed = 1;
698701
else if (best->sched_class == SCHED_CLASS_CFS && best->vruntime < current->vruntime) switch_needed = 1;
@@ -967,6 +970,7 @@ void process_exit(process_t* proc, uint32_t code) {
967970
process_t* next = p->wait_next;
968971
p->wait_next = 0;
969972
p->state = PROCESS_READY;
973+
enqueue_task(p);
970974
p = next;
971975
}
972976
queue->head = 0;
@@ -1098,6 +1102,8 @@ process_t* wait_queue_wake_one(wait_queue_t* queue) {
10981102

10991103
proc->wait_next = 0;
11001104
proc->state = PROCESS_READY;
1105+
enqueue_task(proc);
1106+
11011107
spin_unlock(&sched_lock);
11021108
return proc;
11031109
}
@@ -1115,6 +1121,7 @@ uint32_t wait_queue_wake_all(wait_queue_t* queue) {
11151121
process_t* next = proc->wait_next;
11161122
proc->wait_next = 0;
11171123
proc->state = PROCESS_READY;
1124+
enqueue_task(proc);
11181125
proc = next;
11191126
count++;
11201127
}

src/mem/heap.c

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,69 @@ uint32_t heap_free_bytes(void) {
9696
}
9797

9898
void* aligned_alloc(uint32_t size, uint32_t align) {
99+
if (size == 0 || align == 0 || !heap_head) {
100+
return 0;
101+
}
99102
if (align < 16) {
100103
align = 16;
101104
}
102105
if ((align & (align - 1)) != 0) {
103106
return 0;
104107
}
105-
uint32_t aligned_size = align_up(size, align);
106-
return kmalloc(aligned_size);
108+
109+
size = align_up(size, 16);
110+
heap_block_t* current = heap_head;
111+
while (current) {
112+
if (current->free) {
113+
uint32_t data_ptr = (uint32_t)current + sizeof(heap_block_t);
114+
uint32_t aligned_ptr = align_up(data_ptr, align);
115+
uint32_t padding = aligned_ptr - data_ptr;
116+
117+
uint32_t required_size = size + padding;
118+
119+
if (current->size >= required_size) {
120+
// If there's padding, we MUST split the block so that the
121+
// returned pointer has its header immediately before it.
122+
if (padding > 0) {
123+
while (padding < sizeof(heap_block_t)) {
124+
// Not enough space for a header in the padding.
125+
// We need more padding to fit a header.
126+
// Instead, we move to the NEXT aligned address.
127+
aligned_ptr += align;
128+
padding = aligned_ptr - data_ptr;
129+
required_size = size + padding;
130+
131+
if (current->size < required_size) {
132+
goto next_block;
133+
}
134+
}
135+
136+
// Now padding >= sizeof(heap_block_t).
137+
// We can split.
138+
uint32_t old_size = current->size;
139+
current->size = padding - sizeof(heap_block_t);
140+
141+
heap_block_t* next = (heap_block_t*)((uint8_t*)current + padding);
142+
next->size = old_size - padding;
143+
next->free = 1;
144+
next->next = current->next;
145+
current->next = next;
146+
147+
// The block we want is 'next'
148+
current = next;
149+
}
150+
151+
// Now split at the end if needed
152+
split_block(current, size);
153+
current->free = 0;
154+
155+
return (void*)((uint8_t*)current + sizeof(heap_block_t));
156+
}
157+
}
158+
next_block:
159+
current = current->next;
160+
}
161+
return 0;
107162
}
108163

109164
void kheap_stats(uint32_t* total_bytes, uint32_t* free_bytes) {

0 commit comments

Comments
 (0)