Merge branch 'funny' into 'mommy'
Funny See merge request fekhesk/vap!1
This commit is contained in:
commit
e823fa3080
4 changed files with 37 additions and 189 deletions
|
@ -20,18 +20,12 @@ vap_get_real:
|
|||
// enter real mode
|
||||
mtsrr0 5
|
||||
mfmsr 31
|
||||
// MSR_IR (1 << 5) = 0
|
||||
// MSR_DR (1 << 4) = 0
|
||||
// MSR_EE (1 << 15) = 0
|
||||
lis 30, ~0@h
|
||||
ori 30, 30, ~((1 << 15) | (1 << 5) | (1 << 4))@l
|
||||
and 31, 31, 30
|
||||
mtsrr1 31
|
||||
li 31, (1 << ((32-1) - 19))
|
||||
mtmsr 31
|
||||
|
||||
// now we can rfi to so_real
|
||||
sync
|
||||
isync
|
||||
rfi
|
||||
.global vap_get_fake
|
||||
.extern VAP_KERN_BASE
|
||||
.extern VAP_KERN_PHOF
|
||||
|
@ -39,44 +33,7 @@ vap_get_real:
|
|||
vap_get_fake:
|
||||
// we are now in actual real mode, the registers shouldn't have changed
|
||||
|
||||
// first things first, use the translation table to remap the kernel's memory
|
||||
|
||||
#define PAGE_WIDTH 12
|
||||
#define PAGE_SIZE (1 << PAGE_WIDTH)
|
||||
|
||||
// some values for page copying, very much inspired by helenos's ppc32 port
|
||||
li 31, PAGE_SIZE >> 2
|
||||
li 30, 0
|
||||
|
||||
page_copy:
|
||||
cmpwi 4, 0 // are we at 0 pages (done)?
|
||||
beq page_copy_done // if so, jump to the end
|
||||
|
||||
mtctr 31 // set the counter to PAGE_SIZE >> 2
|
||||
lwz 29, 0(3) // load the physical address of the page to copy
|
||||
|
||||
page_copy_loop:
|
||||
lwz 28, 0(29) // load the word to copy
|
||||
stw 28, 0(30) // store the word to the new page
|
||||
|
||||
// ensure everything's synced
|
||||
dcbst 0, 30
|
||||
sync
|
||||
icbi 0, 30
|
||||
sync
|
||||
isync
|
||||
|
||||
addi 29, 29, 4 // increment the source pointer
|
||||
addi 30, 30, 4 // increment the destination pointer
|
||||
bdnz page_copy_loop // loop
|
||||
// end of page_copy_loop
|
||||
// increment the translation table pointer
|
||||
addi 3, 3, 4
|
||||
// decrement the number of pages left
|
||||
subi 4, 4, 1
|
||||
b page_copy // loop
|
||||
|
||||
page_copy_done:
|
||||
// for the first 256MiB, virtual=physical
|
||||
|
||||
// normally i'd write register names as their true values, but with the bat registers
|
||||
// that'd just make things purely unreadable
|
||||
|
@ -116,138 +73,24 @@ vap_get_fake:
|
|||
mtspr dbat3u, 30
|
||||
mtspr dbat3l, 30
|
||||
|
||||
// here we define a macro for calculating the bat register values
|
||||
// the bat registers are referred to as "upper" and "lower" registers
|
||||
// the upper register contains the virtual address of the page, and the lower register contains
|
||||
// the physical address of the page, as well as some other information
|
||||
// if you want to learn more about this, i'd recommend reading this pdf:
|
||||
// http://www.cs.cmu.edu/~412-s05/projects/9mac/PowerPC_Memory.pdf
|
||||
// there are two notable things about this macro:
|
||||
// 1. lower and upper are registers that the lower and upper bat registers should be set to
|
||||
// their initial values do not matter
|
||||
// 2. i kinda just stole this from helenos, i'm sorry ):
|
||||
.macro BAT_COMPUTE base size mask lower upper kern_base
|
||||
lis \upper, 0x0002
|
||||
cmpw \size, \upper // check if we have less than 128kib remaining to map
|
||||
blt finish_bat // if so, jump to the end
|
||||
// now we can set up the bat registers
|
||||
li 7, ((0x7FF<<2)|2)
|
||||
li 8, ((2<<3)|2)
|
||||
|
||||
li \upper, 18
|
||||
srw \mask, \size, \upper // calculate the mask (size >> 18)
|
||||
sync
|
||||
isync
|
||||
|
||||
// create the block length mask by duplicating the leading 1 14 times
|
||||
// the block length mask indicates the length by number of bits set
|
||||
li \upper, 14
|
||||
mtctr \upper
|
||||
li \upper, 1
|
||||
0:
|
||||
srw \lower, \mask, \upper
|
||||
or \mask, \mask, \lower
|
||||
bdnz 0b
|
||||
// end of 0:
|
||||
// & the mask with 0x07ff to assure that we map at most 256mib
|
||||
andi. \mask, \mask, 0x07ff
|
||||
mtspr dbat0u, 7
|
||||
mtspr dbat0l, 8
|
||||
sync
|
||||
isync
|
||||
mtspr ibat0u, 7
|
||||
mtspr ibat0l, 8
|
||||
sync
|
||||
isync
|
||||
|
||||
// calculate the upper register
|
||||
// the upper register contains:
|
||||
// 1. the virtual address of the page
|
||||
// 2. the block length mask
|
||||
// 3. kernel access bit (1 << 2)
|
||||
// 4. user access bit (1 << 1)
|
||||
// we don't have a userspace yet! so we'll just set the kernel access bit to 1
|
||||
// and the user access bit to 0
|
||||
li \upper, 2
|
||||
slw \mask, \mask, \upper
|
||||
ori \mask, \mask, 0x0002
|
||||
// zero the rest
|
||||
|
||||
lis \upper, (\kern_base + \base)@l
|
||||
or \upper, \upper, \mask
|
||||
|
||||
// calculate the lower register
|
||||
// the lower register contains:
|
||||
// 1. the physical address of the page
|
||||
// 2. storage access controls
|
||||
// 3. protection bits
|
||||
lis \lower, \base
|
||||
ori \lower, \lower, 0x0002
|
||||
.endm
|
||||
|
||||
// now we are finally ready to set the bat registers!
|
||||
// we will load into r29 either 256MiB or the remaining memory amount, whichever is smaller
|
||||
lis 30, 268435456@h
|
||||
ori 30, 30, 268435456@l
|
||||
// reminder that r7 contains the amount of memory we have
|
||||
cmpw 7, 30
|
||||
blt bat0_memsmaller
|
||||
|
||||
// 256mib is smaller
|
||||
mr 29, 30
|
||||
b bat0_constsmaller
|
||||
|
||||
bat0_memsmaller:
|
||||
mr 29, 7
|
||||
bat0_constsmaller:
|
||||
BAT_COMPUTE 0x0000 29 28 27 26 VAP_KERN_PHOF
|
||||
mtspr ibat0u, 26
|
||||
mtspr ibat0l, 27
|
||||
mtspr dbat0u, 26
|
||||
mtspr dbat0l, 27
|
||||
|
||||
// now we will do the same thing for bat 1
|
||||
sub 7, 7, 29 // decrement the amount of memory left
|
||||
|
||||
cmpw 7, 30
|
||||
blt bat1_memsmaller
|
||||
|
||||
// 256mib is smaller
|
||||
mr 29, 30
|
||||
b bat1_constsmaller
|
||||
|
||||
bat1_memsmaller:
|
||||
mr 29, 7
|
||||
bat1_constsmaller:
|
||||
BAT_COMPUTE 0x1000 29 28 27 26 VAP_KERN_PHOF
|
||||
mtspr ibat1u, 26
|
||||
mtspr ibat1l, 27
|
||||
mtspr dbat1u, 26
|
||||
mtspr dbat1l, 27
|
||||
|
||||
// now we will do the same thing for bat 2
|
||||
sub 7, 7, 29 // decrement the amount of memory left
|
||||
|
||||
cmpw 7, 30
|
||||
blt bat2_memsmaller
|
||||
|
||||
// 256mib is smaller
|
||||
mr 29, 30
|
||||
b bat2_constsmaller
|
||||
|
||||
bat2_memsmaller:
|
||||
mr 29, 7
|
||||
bat2_constsmaller:
|
||||
BAT_COMPUTE 0x2000 29 28 27 26 VAP_KERN_PHOF
|
||||
mtspr ibat2u, 26
|
||||
mtspr ibat2l, 27
|
||||
mtspr dbat2u, 26
|
||||
mtspr dbat2l, 27
|
||||
|
||||
// now we will do the same thing for bat 3
|
||||
sub 7, 7, 29 // decrement the amount of memory left
|
||||
|
||||
cmpw 7, 30
|
||||
blt bat3_memsmaller
|
||||
|
||||
// 256mib is smaller
|
||||
mr 29, 30
|
||||
b bat3_constsmaller
|
||||
|
||||
bat3_memsmaller:
|
||||
mr 29, 7
|
||||
bat3_constsmaller:
|
||||
BAT_COMPUTE 0x3000 29 28 27 26 VAP_KERN_PHOF
|
||||
mtspr ibat3u, 26
|
||||
mtspr ibat3l, 27
|
||||
mtspr dbat3u, 26
|
||||
mtspr dbat3l, 27
|
||||
|
||||
finish_bat:
|
||||
// theoretically, we should be done with the bat registers now
|
||||
|
@ -260,7 +103,8 @@ vap_get_fake:
|
|||
// we need to set the srr1 register to the value of the msr register
|
||||
// but also re-enable MSR_IR and MSR_DR so that we can use the bat registers
|
||||
mfmsr 31
|
||||
ori 31, 31, ((1 << 5) | (1 << 4))@l
|
||||
li 31, ((1 << ((32-1) - 19)) | (1 << ((32-1) - 26)) | (1 << ((32-1) - 27)))
|
||||
// enable bit 30 to allow system resets to be recoverable
|
||||
mtsrr1 31
|
||||
|
||||
//mr 1, 8 // restore the stack pointer
|
||||
|
|
|
@ -55,12 +55,7 @@ pub fn bootstrap() -> ! {
|
|||
|
||||
debug!("phys_translation_table: {:x}", phys_translation_table);
|
||||
debug!("page_count: {:x}", page_count);
|
||||
debug!("kernal base: {:x}", VAP_KERN_BASE as usize);
|
||||
debug!("vap_get_real: {:x}", vap_get_real as usize);
|
||||
debug!("phys_get_fake: {:x}", phys_get_fake);
|
||||
debug!("vap_get_fake: {:x}", vap_get_fake as usize);
|
||||
debug!("so_fake: {:x}", so_fake as usize);
|
||||
debug!("phys_so_fake: {:x}", translate_to_phys(so_fake as usize).unwrap());
|
||||
debug!("phys_vap_get_fake: {:x}", phys_vap_get_fake);
|
||||
debug!("mem_size: {:x}", mem_size);
|
||||
debug!("vap_stack: {:x}", VAP_STACK as usize);
|
||||
debug!("openfirmware entry fn: {:x}", unsafe {
|
||||
|
@ -70,7 +65,7 @@ pub fn bootstrap() -> ! {
|
|||
debug!("filled vap allocator with available memory, see you on the flip side!");
|
||||
|
||||
unsafe {
|
||||
vap_get_real(phys_translation_table, page_count, phys_get_fake, so_fake as usize, mem_size, VAP_STACK as usize);
|
||||
vap_get_real(phys_translation_table, page_count, phys_vap_get_fake, finalize_bootstrapping as usize, mem_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,9 +80,11 @@ extern "C" fn test1() {
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn finalize_bootstrapping() -> ! {
|
||||
//test1();
|
||||
panic!("test");
|
||||
memory::ppc32::allocation::VapAllocator::init();
|
||||
// we made it!
|
||||
debug!("hiiii");
|
||||
let available = get_available_memory();
|
||||
debug!("available memory: {:?}", available);
|
||||
memory::VapAllocator::init(available);
|
||||
debug!("initialised vap allocator");
|
||||
debug!("patching interrupt vectors");
|
||||
patch_interrupt_vectors();
|
||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -3,6 +3,7 @@
|
|||
#![feature(lang_items)]
|
||||
#![feature(asm_experimental_arch)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(lazy_cell)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
|
@ -252,6 +253,12 @@ pub fn kernel_main() -> ! {
|
|||
stack_pointer
|
||||
};
|
||||
|
||||
println!("bootstrapping");
|
||||
bootstrap::bootstrap();
|
||||
println!("initializing scheduler");
|
||||
scheduling::add_task(None, kernel_callback).expect("failed to add kernel callback task");
|
||||
|
||||
//debug!("constructing terminal window");
|
||||
//terminal::construct_terminal_window();
|
||||
//macros::USE_RAW.store(false, core::sync::atomic::Ordering::SeqCst);
|
||||
unsafe { scheduling::init_scheduler() };
|
||||
loop {}
|
||||
}
|
|
@ -137,6 +137,7 @@ pub extern "C" fn scheduler_callback(savestate: *const SaveState) -> ! {
|
|||
// set the stack pointer to the end of the stack
|
||||
task.savestate.sp = stack as u32 + 0x100000;
|
||||
task.stack_base = stack as usize;
|
||||
//debug!("added task {} to scheduler", task.uuid);
|
||||
|
||||
// if the next task points to a task that isn't empty, then we need to push the task
|
||||
if scheduler.tasks.get(scheduler.next_task as usize).is_none() || scheduler.tasks[scheduler.next_task as usize].is_some() {
|
||||
|
@ -227,8 +228,7 @@ pub extern "C" fn scheduler_callback(savestate: *const SaveState) -> ! {
|
|||
// reset the last_run value of the task with the highest priority
|
||||
scheduler.tasks[index_with_highest_priority].as_mut().unwrap().last_run = 0;
|
||||
|
||||
// set the current task to the task with the highest priority
|
||||
scheduler.current_task = scheduler.tasks[index_with_highest_priority].as_mut().unwrap().uuid;
|
||||
//debug!("now running task {} with srr0 {:x}", scheduler.current_task, scheduler.tasks[index_with_highest_priority].as_mut().unwrap().savestate.srr0);
|
||||
|
||||
// return to the task with the highest priority
|
||||
unsafe {
|
||||
|
|
Loading…
Add table
Reference in a new issue