Page 1 of 1

HigherHalfKernel / Paging Query

Posted: Thu Jul 26, 2007 4:57 pm
by sparky
Hi all,

Ive spent the last few days working on my memory manager, and although I have paging enabled and everything booted fine. Im still a bit confused about a few things, mainly with regards to higherhalf kernel.
With GRUB (if you want to set up paging right from the start)

GRUB will load your kernel at the desired physical target address, but it will leave segments in the GDT with a 0 base and it will not enable paging.


With GRUB (if you don't want to set up paging right from the start)

Even with GRUB it's still possible to use TimRobinson's GDT trick: just set up a "fake" GDT then jump to your C code and enable paging. See HigherHalfWithGdt
Is that correct about when u setup paging? I mean the higherhalfwithgdt tutorial seems to enable paging from the beginning? I dont want to enable paging from the beginning. As i understand it, if i dont enable paging from the beginning i can install interrupt handlers and the like prior to enabling paging, and so i can handle errors such as protection errors with my own functions?

At the moment I have my kernel working using the higherhalfwithgdt but i dont want to enable paging till later down my kernel initialisation.

Any help is much appreciated :!:

Posted: Thu Jul 26, 2007 5:55 pm
by pcmattman
One way to do this is to do what I do.

I don't have a higher-half kernel, my kernel takes up the first 4 MB. All userland programs are linked to start at 0x40000.

This way I only need to identity map the first 4 MB - much easier than setting up for a higher-half kernel.

Posted: Thu Jul 26, 2007 6:38 pm
by sparky
Ive got it working now so i dont need to enable paging from the onset by tweaking about with the segment bases. Last time i tried this, i forgot to convert the address of video memory from physical to virtual since it was now somewhere just below the 3gb mark.

However now i seem to have a problem whereby when i reach the end of my kernel [ for ( ;; ) ]. bochsstops and displays:

(0) [0x00100e35] 0008:c0000e35 (unk. ctxt): jmp .+0xfffffffe (0xbfff0e35) ; ebfe

Any ideas what may be causing this :?:

Posted: Thu Jul 26, 2007 6:55 pm
by frank
Doesn't for( ;; ) compile too jmp $ which is essentially what the bochs output is showing? Or are you asking why it stops?

Posted: Thu Jul 26, 2007 7:55 pm
by sparky
Yea asking why it stops, prior to modifying my gdt and memory manager routines. Bochs would loop and allow very basic keyboard/screen input/output.

Now it just produces that line and using continue in the bochs debugger restarts the kernel :(

Posted: Fri Jul 27, 2007 2:34 am
by JamesM
you usually get a register dump in bochsout.txt. We/you need to see that.

Posted: Fri Jul 27, 2007 7:25 am
by sparky

Code: Select all

00023747285i[BIOS ] *** int 15h function AX=00C0, BX=0000 not yet supported!
00065803635e[CPU0 ] load_seg_reg(DS): valid bit cleared
00065803635e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00065803635e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00065803635i[CPU0 ] protected mode
00065803635i[CPU0 ] CS.d_b = 32 bit
00065803635i[CPU0 ] SS.d_b = 32 bit
00065803635i[CPU0 ] | EAX=80000010  EBX=0002bb20  ECX=00000f30  EDX=00000400
00065803635i[CPU0 ] | ESP=c0007fd0  EBP=00067ee4  ESI=0002bc73  EDI=0002bc74
00065803635i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf AF PF cf
00065803635i[CPU0 ] | SEG selector     base    limit G D
00065803635i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00065803635i[CPU0 ] |  CS:0008( 0001| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] |  DS:0010( 0002| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] |  SS:0010( 0002| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] |  ES:0010( 0002| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] |  FS:0010( 0002| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] |  GS:0010( 0002| 0|  0) 40100000 000fffff 1 1
00065803635i[CPU0 ] | EIP=c0000082 (c0000082)
00065803635i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x00000000
00065803635i[CPU0 ] | CR3=0x00105000 CR4=0x00000000
00065803635i[CPU0 ] >> mov ds, ax : 8ED8
00065803635e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00065803635i[SYS  ] bx_pc_system_c::Reset(SOFTWARE) called

Posted: Fri Jul 27, 2007 8:37 am
by AJ
You are triple-faulting. It looks like an interrupt or IRQ is happening which you do not have a handler for (or the handler / stack is not paged in).

Cheers,
Adam

Posted: Fri Jul 27, 2007 11:01 am
by sparky
I cant understand why it only triple faults once it reaches the for loop though?

If i enable paging and install the new gdt with base segment of 0. the kernel loads fine.

Why do i need to enable paging and/or install the new gdt b4 entering the final for loop ?

Thanks guys, ive really learned alot these last few days.

Posted: Fri Jul 27, 2007 7:43 pm
by sparky
ok, quick question regarding my physical memory manger,

now that i have segments with a base of 0x40000000 and kernel is in the higher half. The addresses of the pages that i allocate using my stack will be higher half addresses right? eg. 0xc0101000

And these are logical addresses that are converted to linear addresses using the segment base, correct? And with paging not yet enabled the linear addresses equal the physical address ?

If these are correct, I cant understand why with the higherhalf tutorial in the init_paging function, there is any need to convert the virtual address of the pagedir/table into physical addresses, wont the processor take care of this due to the segment base address?

Code: Select all

unsigned long vpagedir[1024] __attribute__ ((aligned (4096)));
unsigned long vpagetable[1024] __attribute__ ((aligned (4096)));

void
init_paging(multiboot_info_t *mbi, unsigned long end)
{
  /* Pointers to the page directory and the page table */
  void *ppagedir = 0;
  void *ppagetable = 0;
  int k = 0; /* counter */

  /* Translate the page directory/table from virt to phys address */
  ppagedir = (char *)vpagedir + 0x40000000;
  ppagetable = (char *)vpagetable + 0x40000000;
  /* continued... */
just want to clarify these few points so i can finalise the physical manager and move onto the virtual manager.

thanks in advance.

Posted: Sat Jul 28, 2007 8:09 am
by jnc100
cr3, page directory entries and page table entries require physical addresses (its in the Intel manuals).

The reasoning is thus:

logical address -> segments -> linear address -> paging -> physical address

If either a logical address or linear address were provided for cr3, that implies that the new page directory you want to switch to must already exist in the linear address space. Often this is not the case when performing task switching (you just store the physical address of each process' page dir). Thus, the cpu expects physical addresses.

Regards,
John.