OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Feb 02, 2023 9:18 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Calculate the address spaces my kernel is occupying?
PostPosted: Thu Jul 28, 2022 7:42 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
I have set the starting address of my linker to be at 16 bytes using linker.ld:
Code:
ENTRY(_start)
SECTIONS
{
   . = 16;
}



I'm not sure if this config makes all the .data and .text sections to be right next to each other?
If it does then is there a way to see how much memory the kernel itself is occupying after grub loads it into memory? i.e how can the kernel tell where the safe and free address space starts which wont overwrite the kernel itself?

For the sake of simplicity don't worry about stack at the moment.


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Thu Jul 28, 2022 8:03 pm 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1047
Yes, change your linker script to this
Code:
ENTRY(_start)
SECTIONS
{
       . = 16;
       .text : ALIGN(4K)
   {
      *(.text)
   }

   /* Read-only data. */
   .rodata : ALIGN(4K)
   {
      *(.rodata)
   }

   /* Read-write data (initialized) */
   .data : ALIGN(4K)
   {
      *(.data)
   }

   /* Read-write data (uninitialized) and stack */
   .bss : ALIGN(4K)
   {
      *(COMMON)
      *(.bss)
   }
        end = .;
}

Then in you C code do:
Code:
extern uint32_t end[];
uint32_t ksize = end - 16;

ksize contains the size of you kernel in bytes.

I included sections in the above linker script because it's a good idea to be explicit about alignment. One more thing: putting your kernel's base at address 0x16 is not a good idea for a number of reasons. That region of memory is reserved by the BIOS. I recommend putting your kernel at 0x100000, as that is not used by the BIOS for anything.

Look at the memory map page on the wiki for more info on this.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Thu Jul 28, 2022 8:18 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
Thank you, can a pointer be used instead of the array? i.e something like this
```
extern uint32_t *end;
```
or an array must be used?


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Thu Jul 28, 2022 8:54 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
Looks like it has to be an array, compiler needs to do it's trick where it makes an array look like a pointer. It's not allocating an actual pointer variable, so arrays are needed.


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 2:00 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 93
nexos wrote:
Yes, change your linker script to this
Code:
ENTRY(_start)
SECTIONS
{
       . = 16;
       .text : ALIGN(4K)

That seems a little whack. Since you've just set ". = 16" won't the next line put ".text" right on the 4k mark? Which means ". = 16" is effectively ". = 4K".

Quote:
Then in you C code do:
Code:
extern uint32_t end[];
uint32_t ksize = end - 16;

ksize contains the size of you kernel in bytes.


No, it won't, due to the kernel really starting at 4k and due to the fact that subtracting 16 from a uint32_t pointer will effectively subtract 64 (i.e. 16 * sizeof(uint32_t)) before the conversion back to integer. And you really should use a cast (from pointer type back to uint32_t). (And if this is for a 64-bit kernel you'll want to use a uint64_t instead, or you'll get a compilation error).

I suggest using an opaque, never-defined struct type instead of an array, and casting to char * for the arithmetic:

Code:
extern struct opaque end;
uint32_t ksize = (uint32_t)((char *)&end - 32);


(Though as I said, subtracting 32 probably won't give you the right answer here anyway).

Using an incomplete struct type prevents you from accidentally using the *value* instead of the *address*.

Quote:
One more thing: putting your kernel's base at address 0x16 is not a good idea for a number of reasons. That region of memory is reserved by the BIOS. I recommend putting your kernel at 0x100000, as that is not used by the BIOS for anything.

The address is virtual, it doesn't need to correspond to the physical address where the kernel is loaded.


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 4:24 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 878
Building on the previous reply, why not simply define a symbol at the start of the kernel as well. This way you don't need to do any arithmetics using magic numbers. Another suggestion would be to just declare the symbols as char[] and get rid of the casts. Finally use size_t to hold the kernel size, don't hardcode a uint32_t or uint64_t there...

Code:
extern char _kernel_start[];
extern char _kernel_end[];
...
size_t kernel_size = _kernel_end - kernel_start;

_________________
https://github.com/kiznit/rainbow-os


Last edited by kzinti on Fri Jul 29, 2022 4:48 am, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 4:44 am 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1047
davmac314 wrote:
That seems a little whack. Since you've just set ". = 16" won't the next line put ".text" right on the 4k mark? Which means ". = 16" is effectively ". = 4K".

It depends on if you count alignment space a part of the kernel. But it would make more sense to just align the entire base on a 4K aligned area.
davmac314 wrote:
No, it won't, due to the kernel really starting at 4k and due to the fact that subtracting 16 from a uint32_t pointer will effectively subtract 64 (i.e. 16 * sizeof(uint32_t)) before the conversion back to integer. And you really should use a cast (from pointer type back to uint32_t). (And if this is for a 64-bit kernel you'll want to use a uint64_t instead, or you'll get a compilation error).

I suggest using an opaque, never-defined struct type instead of an array, and casting to char * for the arithmetic:

I admit that part of my post was erroneous. I would recommend this then:
Code:
extern uint8_t end;
uint32_t ksize = (uint32_t)&end - 16;

Then you avoid the the more confusing casts.
davmac314 wrote:
The address is virtual, it doesn't need to correspond to the physical address where the kernel is loaded.

The OP hasn't specified if they have set up paging, so I don't know.
Quote:
Thank you, can a pointer be used instead of the array? i.e something like this
```
extern uint32_t *end;
```
or an array must be used?

It could be a pointer, using would just need to take the address of the pointer, e.g.:
Code:
extern uint32_t* end;
uint32_t ksize = (uint32_t)&end - 16;

kzinti wrote:
Building on the previous reply, why not simply define a symbol at the start of the kernel as well.

That's a good idea. I would definitely recommend doing that.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 12:49 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
Is `ALIGN(4K)` really needed here? Can it be omitted or the value changed? Also I don't have paging enabled.


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 2:07 pm 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1047
nightcrawler wrote:
Is `ALIGN(4K)` really needed here? Can it be omitted or the value changed? Also I don't have paging enabled.

If paging is not used, than it is not needed.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 2:56 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
So my original method
Code:
ENTRY(_start)
SECTIONS
{
   . = 16;
}

is ok to use? or we still need sections without alignment?


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 3:46 pm 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1047
Yes, as long as you define the start and end symbols as kzinti suggested. Also, remember that with paging disabled, you should probably put your kernel above 0x100000, as 0x16 physical is reserved.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 4:49 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
Thanks, so in its current form, would it look like this?
Code:
ENTRY(_start)
SECTIONS
{
       . = 16;
        start = .;
        end = .;
}

i.e `start` is put before `16` or after it?


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 6:28 pm 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 878
Why do you want that 16 there at all? What is it doing for you?

_________________
https://github.com/kiznit/rainbow-os


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 8:36 pm 
Offline

Joined: Thu Aug 08, 2019 8:21 am
Posts: 17
Assume its any other number, like 1M, would this work?
Code:
        . = 1M;
        start = .;
        end = .;


Top
 Profile  
 
 Post subject: Re: Calculate the address spaces my kernel is occupying?
PostPosted: Fri Jul 29, 2022 9:21 pm 
Offline
Member
Member

Joined: Tue Feb 18, 2020 3:29 pm
Posts: 1047
You need to explicitly put the sections between start and end. As it currently stands, the sections will probably be after the end symbol.

_________________
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group