Questions on running in higher half

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
IanSeyler
Member
Member
Posts: 326
Joined: Mon Jul 28, 2008 9:46 am
Location: Ontario, Canada
Contact:

Questions on running in higher half

Post by IanSeyler »

Hi everyone,

Currently, BareMetal OS and it's programs run in lower memory (programs are loaded to 0x20000). This has been working well enough for small programs but I think I will run into issues once the programs get larger and require more memory. The issues I see are in regards to the various memory holes in the first 4GiB of memory.

Can I get around these memory holes by running in the higher half? Ideally I want the application to use memory as a contiguous space without holes.

My 64-bit loader uses an identity map when setting up the PML4 so that 0x0 is the same memory as 0xFFFF800000000000. After I jump to the higher half can I then remove the identity map? Can I still access the APIC/IOAPIC via their low addresses?

Thanks,
Ian
BareMetal OS - http://www.returninfinity.com/
Mono-tasking 64-bit OS for x86-64 based computers, written entirely in Assembly
Casm
Member
Member
Posts: 221
Joined: Sun Oct 17, 2010 2:21 pm
Location: United Kingdom

Re: Questions on running in higher half

Post by Casm »

If you are running in 64 bit mode, you have got to have paging enabled, and an identity map is as close as you can get to not having it enabled. In principle, you can establish any other kind of mapping you like.

The holes are mostly at the top of the first 4Gb, and an operating system ought to have no trouble finding out where they are at boot time. Either through int 15h, ax = 0E820h, or through the equivalent EFI service. The holes are there, and there is no way they can be avoided since memory mapping became the in thing. Unless you declare a whole swathe of memory out of bounds at the top on the first 4Gb.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Questions on running in higher half

Post by bluemoon »

ReturnInfinity wrote:Can I get around these memory holes by running in the higher half? Ideally I want the application to use memory as a contiguous space without holes.
Memory holes are unusable physical address. Higher half kernel requires you use paging, which deals with logical address, you have the freedom to map discrete physical addresses, so you naturally solve the memory hole issue. Also, you can work with contiguous logical address as you wish.
ReturnInfinity wrote:My 64-bit loader uses an identity map when setting up the PML4 so that 0x0 is the same memory as 0xFFFF800000000000. After I jump to the higher half can I then remove the identity map? Can I still access the APIC/IOAPIC via their low addresses?
Once you jump into higher half, you may un-map the low address if you are not using it anymore. However, you may want to keep lowest 1MB (or 16MB) mapped in early development stage to access convenient stuff like VGA text and DMA buffers until you implement modern solutions.
ReturnInfinity wrote:Can I still access the APIC/IOAPIC via their low addresses?
With paging enabled, you access IOAPIC with logical address, which you map into the physical address (configured with MSRs) in page table. So no, you can't access them with low address after you un-map those identity mapped entries, but you can access them with any address you map in page table.
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: Questions on running in higher half

Post by Antti »

I had a very simple solution to access physical memory.

Code: Select all

void PhysicalMemoryWrite8(void *address, uint8_t value);
void PhysicalMemoryWrite16(void *address, uint16_t value);
void PhysicalMemoryWrite32(void *address, uint32_t value);

uint8_t PhysicalMemoryRead8(void *address);
uint16_t PhysicalMemoryRead16(void *address);
uint32_t PhysicalMemoryRead32(void *address);
These functions create a lock, map a temporary page (if not correct already, e.g. sequential access), do the access, and release the lock. Inefficient? Yes!. However, it worked very well. Expecially when access is needed only when doing initialization etc.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Questions on running in higher half

Post by bluemoon »

Antti wrote:I had a very simple solution to access physical memory.

Code: Select all

void PhysicalMemoryWrite8(void *address, uint8_t value);
void PhysicalMemoryWrite16(void *address, uint16_t value);
void PhysicalMemoryWrite32(void *address, uint32_t value);

uint8_t PhysicalMemoryRead8(void *address);
uint16_t PhysicalMemoryRead16(void *address);
uint32_t PhysicalMemoryRead32(void *address);
These functions create a lock, map a temporary page (if not correct already, e.g. sequential access), do the access, and release the lock. Inefficient? Yes!. However, it worked very well. Expecially when access is needed only when doing initialization etc.
Instead of bundle the read/write with lock/unlock, I break them down into mmap, munmap, and read/write(with normal pointer access).
Post Reply