Linking per-CPU variables to a special area?

Programming, for all ages and all languages.
Post Reply
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Linking per-CPU variables to a special area?

Post by mariuszp »

My kernel is a flat binary with a multiboot header (mainly because it has a 32-bit glue followed by 64-bit code).

I am using the following linker script at the moment:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(_start)
phys = 0xFFFF800000100000;

SECTIONS
{
	.text phys : AT(phys) {
		code = .;
		*(.bootstrap32)
		*(.text)
		*(.rodata)
		. = ALIGN(4096);
	}

	.data (phys + (data - code)) : AT(phys + (data - code))
	{
		data = .;
		*(.data)
		. = ALIGN(4096);
	}

	.bss (phys + (bss - code)) : AT(phys + (bss - code))
	{
		bss = .;
		*(.bss)
		. = ALIGN(4096);
		end = .;
	}
}
My idea of per-CPU variables would be to put them in a specific section called "data_per_cpu", and have that section linked such that it is at 0xFFFF828000000000 (that's PML4 entry 261). This way, each CPU would have its own copy of the PML4, each having this specific area of memory mapped to a different physical location, hence having per-CPU variables.

However, if I try to put this section inside the ".bss" above, like so:

Code: Select all

. = 0xFFFF828000000000;
_per_cpu_start = .;
*(.data_per_cpu)
_per_cpu_end = .;
The linker tries to fill the entire area from the end of BSS all the way up to 0xFFFF828000000000 with zeores; and that is a good few terabytes of data, so it obviously doesn't work.

Can I somehow force the linker not to put any zeroes or other data in that area, but instead simply relocate references to within the per_cpu_data section to match those addresses?
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: Linking per-CPU variables to a special area?

Post by Velko »

Do not place it inside .bss then. Place it in dedicated section. What about (did not test, based on your linker script):

Code: Select all

    --- snip ---
   .bss (phys + (bss - code)) : AT(phys + (bss - code))
   {
      bss = .;
      *(.bss)
      . = ALIGN(4096);
      end = .;
   }

   . = 0xFFFF828000000000;
   .per_cpu_bss ((phys + (_per_cpu_start - code)) : AT(phys + (_per_cpu_start - code)))
   {
      _per_cpu_start = .;
      *(.data_per_cpu)
      _per_cpu_end = .;
   }
}
Running kernel does not care what was linked to which section. Only VMA addresses matter. And if you use flat binary, bootloader does not know anything about sections either.
If something looks overcomplicated, most likely it is.
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: Linking per-CPU variables to a special area?

Post by mariuszp »

I know that neither the kernel nor the bootloader care about what went into each section; the only reason to put per-cpu variables in a special section is so that the virtual addresses are in an area that can be mapped to a different physical location on each CPU.
User avatar
iansjack
Member
Member
Posts: 4685
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Linking per-CPU variables to a special area?

Post by iansjack »

Flat binaries just make life more difficult. I would highly recommend using Elf-format files.
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: Linking per-CPU variables to a special area?

Post by mariuszp »

I have tried linking it using that script snippet, but it generates a 1.7 TB file.

However, the ".bss" section is never placed in the flat binary. Do I have to somehow tell the linker that ".data_per_cpu" is a BSS section, such that it does not try to actually put it in the binary?
mariuszp
Member
Member
Posts: 587
Joined: Sat Oct 16, 2010 3:38 pm

Re: Linking per-CPU variables to a special area?

Post by mariuszp »

Ah, I got it. The trick was:

Code: Select all

	. = 0xFFFF828000000000;
	_per_cpu_start = .;
	.per_cpu_bss (phys + (_per_cpu_start - code)) (NOLOAD) : AT(phys + (_per_cpu_start - code))
	{
		*(.data_per_cpu)
   	}
   	_per_cpu_end = .;
Post Reply