Assignment 4 - Memory and PIT
92025/5/
Legg til kommentar
222024/1/til 92025/5/
Detaljer
💡 Assignment Files Below!
assignment_files.zip ([Link]
([Link]
Assignment 4 - Memory and PIT
Summary of Deliverable
1. Working memory management
2. Working pit sleep functions
Part 1: Memory Management
In this assignment, you will be implementing memory management for a simple operating system
kernel. The kernel requires proper memory management to manage and allocate memory resources
efficiently. You will be working on initializing the kernel memory manager. Additionally, you will be
implementing the new and delete operators.
Requirements
1. Define extern uint32_t end; below includes in your kernel.c to refer to the memory address where
kernel memory will start.
2. Implement malloc() and free()
3. Add the overloaded new and delete operators for single object and array allocation and
deallocation above your kernel_main function.
4. Add the init_kernel_memory(&end); function in your kernel memory manager.
5. Add the init_paging(); function to set up paging for your kernel.
6. Add the print_memory_layout(); function to display the memory layout of your kernel.
7. Allocate memory using the kernel memory manager with malloc() and the overloaded new
operator.
Note: You must remember to add source files to the kernel target in [Link]
Code Examples
💡 This is defined in your [Link] file. That is why we use "extern"
extern uint32_t end; // This is defined in arch/i386/[Link]
kernel.c Example
int kernel_main_c(uint32_t magic, struct multiboot_info* mb_info_addr) {
// Initialize the monitor (screen output)
monitor_initialize();
// Initialize the Global Descriptor Table (GDT).
init_gdt();
// Initialize the Interrupt Descriptor Table (IDT).
init_idt();
// Initialize the hardware interrupts.
init_irq();
// Initialize the kernel's memory manager using the end address of the kernel.
init_kernel_memory(&end); // <------ THIS IS PART OF THE ASSIGNMENT
// Initialize paging for memory management.
init_paging(); // <------ THIS IS PART OF THE ASSIGNMENT
// Print memory information.
print_memory_layout(); // <------ THIS IS PART OF THE ASSIGNMENT
// Initialize PIT
init_pit(); // <------ THIS IS PART OF THE ASSIGNMENT
// Print a hello world message.
printf("Hello World!\n");
// Call the C++ main function of the kernel.
return kernel_main();
}
[Link] Example
// Existing global operator new overloads
void* operator new(size_t size) {
return malloc(size);
}
void* operator new[](size_t size) {
return malloc(size);
}
// Existing global operator delete overloads
void operator delete(void* ptr) noexcept {
free(ptr);
}
void operator delete[](void* ptr) noexcept {
free(ptr);
}
// Add sized-deallocation functions
void operator delete(void* ptr, size_t size) noexcept {
(void)size; // Size parameter is unused, added to match required signature
free(ptr);
}
void operator delete[](void* ptr, size_t size) noexcept {
(void)size; // Size parameter is unused, added to match required signature
free(ptr);
}
extern "C" int kernel_main(void);
int kernel_main(){
// Allocate some memory using the kernel memory manager
// THIS IS PART OF THE ASSIGNMENT
void* some_memory = malloc(12345);
void* memory2 = malloc(54321);
void* memory3 = malloc(13331);
char* memory4 = new char[1000]();
// More code....
}
After you have integrated memory management, your kernel_main function should look similar to the
one above. You can also define these directly in [Link] if you so choose.
Verification
If malloc and new work are as expected, then it's all good.
Part 2: Programmable Interval Timer
In this part, you are required to implement a driver for the PIT (Programmable Interval Timer) using the
provided header file. The driver should include functions for initializing the PIT, sleeping using
interrupts, and sleeping using busy waiting. You will be working with the 8253/8254 PIT chip, which is
commonly found in IBM PC-compatible computers.
Programmable Interval Timer - OSDev Wiki ([Link]
Requirements
1. Familiarize yourself with the 8253/8254 PIT chip and its functions.
2. Use the provided header file, pit.h as the basis for your implementation.
3. Implement the init_pit() function to initialize the PIT.
4. Implement the sleep_interrupt(uint32_t milliseconds) function to sleep using interrupts for the
specified number of milliseconds.
5. Implement the sleep_busy(uint32_t milliseconds) function to sleep using busy waiting for the
specified number of milliseconds.
6. The above should be implemented in pit.c (Remember to add this to [Link])
Note: Remember to call init_pit() in kernel_main
pit.h Example
#ifndef PIT_H
#define PIT_H
#include
#include
// PIT (Programmable Interval Timer) related macros
#define PIT_CMD_PORT 0x43
#define PIT_CHANNEL0_PORT 0x40
#define PIT_CHANNEL1_PORT 0x41
#define PIT_CHANNEL2_PORT 0x42
#define PC_SPEAKER_PORT 0x61
#define PIT_DEFAULT_DIVISOR 0x4E20 // 20000, which gives about 18.2 Hz (1193180 / 20000)
// IRQ0 related macros
#define PIC1_CMD_PORT 0x20
#define PIC1_DATA_PORT 0x20
#define PIC_EOI 0x20 /* End-of-interrupt command code */
// Custom sleep function constants
#define PIT_BASE_FREQUENCY 1193180
#define TARGET_FREQUENCY 1000 // 1000 Hz
#define DIVIDER (PIT_BASE_FREQUENCY / TARGET_FREQUENCY)
#define TICKS_PER_MS (TARGET_FREQUENCY / TARGET_FREQUENCY)
void init_pit();
void sleep_interrupt(uint32_t milliseconds);
void sleep_busy(uint32_t milliseconds);
#endif
Pseudocode for sleep functions
Function: sleep_busy
Set start_tick to get_current_tick()
Set ticks_to_wait to milliseconds * TICKS_PER_MS
Set elapsed_ticks to 0
While elapsed_ticks is less than ticks_to_wait
a. While get_current_tick() is equal to start_tick + elapsed_ticks
i. Do nothing (busy wait)
b. Increment elapsed_ticks
Function: sleep_interrupt
Set current_tick to get_current_tick()
Set ticks_to_wait to milliseconds * TICKS_PER_MS
Set end_ticks to current_tick + ticks_to_wait
While current_tick is less than end_ticks
a. Execute the following assembly instructions:
i. Enable interrupts (sti)
ii. Halt the CPU until the next interrupt (hlt)
b. Set current_tick to get_current_tick()
Evaluation:
💡 Look at the bottom of the assignment for a printf function that supports numbers
To evaluate if your PIT is working, the following code can be used in kernel_main:
while(true){
printf("[%d]: Sleeping with busy-waiting (HIGH CPU).\n", counter);
sleep_busy(1000);
printf("[%d]: Slept using busy-waiting.\n", counter++);
printf("[%d]: Sleeping with interrupts (LOW CPU).\n", counter);
sleep_interrupt(1000);
printf("[%d]: Slept using interrupts.\n", counter++);
};
Submission
Complete the "Memory and PIT" section for the final report
When done with coding, you can submit a pull request to the UiAIKT github repository to verify that
your submission works (no conflicts and all checks passed)