Re: [PATCH v2 7/7] RISC-V: place .sdata / .srodata / .riscv.attributes
Oleksii Kurochko <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
On 8/26/26 2:04 PM, Jan Beulich wrote: > Of the short-data sections, only .sbss is presently mentioned in the > linker script. Place them next to, but ahead of their "normal" data > sections. > > .riscv.attributes can go towards the tail of the image, next to (ahead of) > debug info. > > Signed-off-by: Jan Beulich <[email protected]> > --- > Seeing where .sbss lives, does positioning really not matter at all? I > would have expected that short-data sections want to live close together, > and specifically close to .text / .init.text (seeing that such data is > accessed using AUIPC). I'm puzzled that the psABI doesn't even mention > them, hence leaving it open how exactly they are to be used. It doesn't, and the reason is that the relevant proximity isn't to .text but to __global_pointer$. The small-data sections exist to let a linker script cluster small objects around that anchor so that ld's relaxation pass can fold an auipc+load pair into a single gp-relative access (-+2 KiB window). That pass is keyed purely on the symbol being defined riscv_global_pointer_value() returns 0 otherwise and the relaxation is skipped. We define no __global_pointer$ and head.S never loads gp (it appears only as a cpu_user_regs slot in entry.S), so every access stays the medany auipc form regardless of section. I confirmed this by linking the same object twice (look at the script below, with and without the symbol: without it, zero gp-relative accesses; with it, the pairs collapse. Worth noting the relaxation is section-agnostic: in the test mentioned below a 400-byte array in plain .bss got gp-relative too, purely because it landed in range. So the sections are a clustering hint, not a mechanism ld keys off. The script I used: ``` mkdir -p /tmp/gp-demo && cd /tmp/gp-demo # 1. Test code: one small variable (-> .sbss) and one large array (-> .bss) cat > s.c <<'EOF' int small_var; /* 4 bytes -> .sbss */ int big_arr[100]; /* 400 bytes -> .bss */ int read_small(void) { return small_var; } int read_big(void) { return big_arr[0]; } EOF # 2. Linker script WITHOUT __global_pointer$ cat > nogp.lds <<'EOF' ENTRY(read_small) SECTIONS { . = 0xffffffffc0000000; .text : { *(.text) *(.text.*) } .data : { *(.sdata .sdata.*) *(.data .data.*) } .bss : { *(.sbss .sbss.*) *(.bss .bss.*) *(COMMON) } /DISCARD/ : { *(.comment) *(.note*) *(.riscv.attributes) } } EOF # 3. Same script, but WITH __global_pointer$ defined sed 's|^ \.data : {| __global_pointer$ = . + 0x800;\n .data : {|' nogp.lds > gp.lds riscv64-linux-gnu-gcc -O2 -march=rv64ima -mabi=lp64 -mcmodel=medany \ -ffreestanding -c s.c -o s.o # Check the INPUT sections: .sbss vs plain .bss (the link merges them, so # inspect s.o, not the linked ELF) echo "### INPUT sections the symbols live in ###" riscv64-linux-gnu-objdump -t s.o | grep -E 'small_var|big_arr' # Link both ways and compare the generated code for L in nogp gp; do riscv64-linux-gnu-ld -T $L.lds s.o -o $L.elf 2>/dev/null echo "=============== $L.lds ===============" riscv64-linux-gnu-objdump -d --no-show-raw-insn $L.elf \ | sed -n '/<read_small>:/,/ret/p;/<read_big>:/,/ret/p' done ``` > > What remains to eliminate orphan section warnings is the placement of > .note.GNU-stack (which perhaps wants dealing with on all of Arm, PPC, and > RISC-V together, ideally unifying with x86) and (odd at the first glance, > but dealt with on x86 as well, i.e. may again want unifying) that of a > number of .rela.* sections. > > --- a/xen/arch/riscv/xen.lds.S > +++ b/xen/arch/riscv/xen.lds.S > @@ -44,6 +44,8 @@ SECTIONS > > BUGFRAMES > > + *(.srodata) > + *(.srodata.*) > *(.rodata) > *(.rodata.*) > VPCI_ARRAY > @@ -92,6 +94,7 @@ SECTIONS > SCHEDULER_ARRAY > HYPFS_PARAM > > + *(.sdata .sdata.*) > *(.data .data.*) > CONSTRUCTORS > } :text > @@ -162,6 +165,8 @@ SECTIONS > /* Section for the device tree blob (if any). */ > .dtb : { *(.dtb) } :text > > + .riscv.attributes : { *(.riscv.attributes) } :text > + Nit: .riscv.attributes is SHT_RISCV_ATTRIBUTES, i.e. non-alloc. :text on it is misleading, and without an explicit address it gets sh_addr from .(location counter) after .dtb. Could we use matching the idiom used for every other non-alloc section in xen.lds.h: .riscv.attributes 0 : { *(.riscv.attributes) } No functional difference either way (objcopy -O binary drops it, and I verified a non-alloc output section doesn't advance dot, so nothing downstream shifts), so purely consistency. Is dropping orphan-handling-y := from arch/riscv/Makefile the intended end of this series? As if I understand correctly with such defintion we will miss warning so everything of that will be missed: cd xen riscv64-linux-gnu-ld -T arch/riscv/xen.lds prelink.o --orphan-handling=warn -o /tmp/t.elf 2>&1 \ | grep 'orphan section' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.note.GNU-stack' from `prelink.o' being placed in section `.note.GNU-stack' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.rela.text' from `prelink.o' being placed in section `.rela.dyn' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.rela.init.text' from `prelink.o' being placed in section `.rela.dyn' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.rela.data.read_mostly' from `prelink.o' being placed in section `.rela.dyn' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.rela.init.data' from `prelink.o' being placed in section `.rela.dyn' /usr/bin/riscv64-linux-gnu-ld: warning: orphan section `.rela.text.header' from `prelink.o' being placed in section `.rela.dyn' Thanks. ~ Oleksii