kernel/pmem.68k
2024-03-19 09:24:10 -05:00

151 lines
4.8 KiB
Plaintext

include vmem.i
include term.i
include cards.i
include string.i
xref _kernel_end_page
section .text, text
public pmem_init
; Initialize the physical memory manager
pmem_init:
movem.l d2/d3/d4, -(a7) ; Save old values of d2, d3, and d4 (callee preserved)
clrfo
pmem_init.buf: fo.b 12
link a6, #__FO ; Create a 12-byte stack frame to use as a buffer for hex_to_ascii
move.w #$1, d0 ; Get the pointer to the ROM card
jsr find_first_card
move.w #$C000, ($F0,a0) ; Enable the card at physical address $C0000000
move.b #$1, ($F3,a0)
move.l #0, d2 ; Map the beginning of the ROM card's RAM into virtual memory
move.l #$C0008000, d0
move.l #$1, d1
move.l #$2, d3
jsr vmem_map_free_to
move.l a0, -(a7) ; Save a0
move.l a0, a1
move.l #$1, d0
jsr vmem_get_free_kernel_pages ; Alocate the stack page
move.l a0, stack_page_addr
move.l a0, a1
move.l #kernel_address_space, a0
move.l (a7)+, a0 ; Restore a0
adda.l #($100-$4), a0
move.l #1, d0 ; d0 holds the physical base address of the RAM card (+ 1 for the enable flag)
move.l #_kernel_end_page, d4 ; Put the physical address of the last kernel page into d4
sub.l #$C01000, d4
ramcard_map_loop:
lea ($4,a0), a0 ; Move to the next RAM card
move.l (a0), a1 ; Load the IO base pointer into a1
cmpa.l #0, a1
beq.w ramcard_map_loop_done ; If the pointer is 0, we have reached the end of the list, so exit the loop
move.l d0, (a1) ; Map the card to the base address in d0
move.l d0, d3 ; Save the base address in d3 for later use
move.l ($4,a1), d1 ; Advance d0 by the size of the card
move.l d1, d2 ; Save the card size in d2 for later use
add.l d1, d0
movem.l d0/a0, -(a7) ; Save base address and RAM card pointer
move.l #pmem_log_name, a0 ; Log the mapped RAM card
jsr term_print
lea.l (pmem_init.buf,a6), a0 ; Print the card size in bytes
move.l d2, d0
jsr hex_to_ascii
lea.l (pmem_init.buf,a6), a0
jsr term_print
move.l #ramcard_log_msg, a0 ; Print " byte RAM card at "
jsr term_print
lea.l (pmem_init.buf,a6), a0 ; Print the card base address
move.l d3, d0
subi.l #1, d0
jsr hex_to_ascii
lea.l (-12,a6), a0
jsr term_println
subi.l #1, d3
rc_map_page_push_loop:
cmp.l d4, d3 ; If the current physical page is used by the kernel binary, skip it
bhi.b .1
add.l #$1000, d3
sub.l #$1000, d2
bra.b rc_map_page_push_loop
.1:
move.l d3, d0 ; Push the frame in d3 and move to the next one
jsr pmem_push_frame
add.l #$1000, d3
sub.l #$1000, d2
bne.b rc_map_page_push_loop ; Loop back if this card has more pages to push
rc_map_pages_pushed:
movem.l (a7)+, d0/a0 ; Restore base address and RAM card pointer
bra.w ramcard_map_loop ; Loop back and map the next card
ramcard_map_loop_done:
move.l a0, d0
andi.l #(~$FFF), d0
move.l d0, a0
move.l #0, d0
jsr vmem_unmap_page
unlk a6 ; Tear down the stack frame
movem.l (a7)+, d2/d3/d4 ; Restore d2, d3, and d4 (callee preserved)
rts
public pmem_push_frame
; Pushes a frame onto the stack
; Frame to push in d0
pmem_push_frame:
move.l d0, -(a7)
move.l #0, d0
move.l stack_page_addr, a0
jsr vmem_get_map_ptr
move.l (a7)+, d0
move.l (a0), d1 ; Read the mapping entry into d1
andi.l #(~$FFF), d1 ; Clear the entry's flags to get the pointer to its physical page
movem.l d1/d2/d3, -(a7)
; Map the stack page to the frame to push
move.l #0, d2
move.l stack_page_addr, a0
move.l #1, d1
move.l #$2, d3
jsr vmem_map_to
move.l stack_page_addr, a0 ; Clear the TLB entry for the mapping page
jsr vmem_clear_tlb_entry
movem.l (a7)+, d1/d2/d3
move.l stack_page_addr, a0 ; Load the address of the stack page into a0
move.l d1, (a0) ; Write the address of the old top frame to the next pointer of the new top
rts
public pmem_pop_frame
; Pops a frame off the stack
; Returns frame address in d0
pmem_pop_frame:
move.l #0, d0 ; Read the mapping entry into d0
move.l stack_page_addr, a0
jsr vmem_get_map_ptr
move.l (a0), d0
andi.l #(~$FFF), d0 ; Clear the entry's flags to get the pointer to its physical frame
move.l stack_page_addr, a1 ; Load the address of the stack page into a1
move.l (a1), d1 ; Get the address of the frame pointed to by the top of the stack
beq.b pop_no_page ; If the pointed-to frame is the null frame, OOM
movem.l d0/d2/d3, -(a7)
; Map the stack page to the pointed-to-frame
move.l d1, d0
move.l #0, d2
move.l stack_page_addr, a0
move.l #1, d1
move.l #$2, d3
jsr vmem_map_to
move.l stack_page_addr, a0 ; Clear the TLB entry for the mapping page
jsr vmem_clear_tlb_entry
movem.l (a7)+, d0/d2/d3
rts
pop_no_page:
move.l #oom_error_str, a0
jsr term_println
stop #$2700
section .data,data
pmem_log_name: dc.b "[PMEM] ",0
ramcard_log_msg: dc.b " byte RAM card at ",0
oom_error_str: dc.b "Out of physical memory",0
section .bss,bss
align 1
stack_page_addr:
ds.b 4