I tried to make a specific section that would be linked to the lower half, but only after the multiboot header, which I wasn't able to get working - so the only option I saw left was rep movsb, but I still don't think that's working properly as the function never returns to the C from which it was called, and I think just ends up running garbage somewhere in lower memory (it never gets to re-enabling paging). I believe the best option here would be to just link to the lower half, but since I couldn't get that to work, I'm not sure what to do. Does anyone know how to make one specific section link normally without the virtual memory offset (and force it to come after the mulriboot header), or have any other way to copy one section of memory to another?
Here is what I've made so far:
Code: Select all
.global copy_page_physical
copy_page_physical:
pushl %eax
pushfl
cli
# get the source and destination addresses, as pushed from C
movl 12(%esp), %esi
movl 16(%esp), %edi
lea (lower_half_cpp), %edx
subl $VIRTUAL_BASE, %edx
# disable paging
movl %cr0, %ecx
andl $0x7FFFFFFF, %ecx
movl %ecx, %cr0
# we shouldn't need to move the stack, unless we need to pop something before re-enabling paging
jmp *%edx
lower_half_cpp: # "lower half CopyPagePhysical"
# movsb needs the number of bytes to copy in ecx, so since we're not storing anything necessary there, that works out
movl $1024, %ecx
rep movsb
# re-enable paging
lea (higher_half_cpp), %edx
movl %cr0, %eax
orl $0x80000000, %eax
movl %eax, %cr0
jmp *%edx
higher_half_cpp:
# magic breakpoint, which *is* triggered, somehow?
xchgw %bx, %bx
popfl
popl %eax
sti
ret #either jumps to nonsense, or is never reached
Code: Select all
/* The bootloader will look at this image and start execution at the symbol
designated as the entry point. */
ENTRY(_start)
/* A few definitions the assembly code can use for physical addresses. */
PHYSICAL_BASE = 0x00100000;
VIRTUAL_BASE = 0xC0000000;
SECTIONS
{
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
loaded at by the bootloader, and add C0000000 (3GB) for paging. */
. = 0xC0100000;
/* Multiboot comes first for GRUB to find, then stack*/
.text ALIGN (0x1000) : AT(ADDR(.text)-0xC0000000)
{
*(.multiboot*)
*(.text*)
}
/* Read-only data. */
.rodata ALIGN (0x1000) : AT(ADDR(.rodata)-0xC0000000)
{
*(.rodata*)
}
/* Read-write data (initialized) */
.data ALIGN (0x1000) : AT(ADDR(.data)-0xC0000000)
{
*(.data*)
}
/* Read-write data (uninitialized) and stack */
.bss ALIGN (0x1000) : AT(ADDR(.bss)-0xC0000000)
{
*(COMMON*)
*(.bss*)
}
KERNEL_END = .;
}