Re: [PATCH 3/4] parisc: Use absolute_pointer for memcmp on fixed memory location

From: Helge Deller
Date: Sun Sep 12 2021 - 16:00:45 EST


* Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>:
> On Sun, Sep 12, 2021 at 9:02 AM Guenter Roeck <linux@xxxxxxxxxxxx> wrote:
> >
> > - running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0);
> > + running_on_qemu = (memcmp(absolute_pointer(&PAGE0->pad0), "SeaBIOS", 8) == 0);
>
> This seems entirely the wrong thing to do, and makes no sense. That
> "&PAGE0->pad0" is a perfectly valid pointer, and that's not where the
> problem is.
>
> The problem is "PAGE0" itself:
>
> #define PAGE0 ((struct zeropage *)__PAGE_OFFSET)
>
> which takes that absolute offset and creates a pointer out of it.
>
> IOW, _that_ is what should have the "absolute_pointer()" thing, and in
> that context the name of that macro and its use actually makes sense.
>
> No?
>
> An alternative - and possibly cleaner - approach that doesn't need
> absolute_pointer() at all might be to just do
>
> extern struct zeropage PAGE0;
>
> and then make that PAGE0 be defined to __PAGE_OFFSET in the parisc
> vmlinux.lds.S file.
>
> Then doing things like
>
> running_on_qemu = !memcmp(&PAGE0.pad0, "SeaBIOS", 8);
>
> would JustWork(tm).

Yes, this second approach seems to work nicely, although the patch
then gets slightly bigger.
Below is a tested patch.
I'll check it some further and apply it to the parisc tree then.

Thanks!
Helge

--------

[PATCH] Define and export PAGE0 in vmlinux.lds.S linker script

Signed-off-by: Helge Deller <deller@xxxxxx>
Suggested-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>

---

diff --git a/arch/parisc/boot/compressed/misc.c b/arch/parisc/boot/compressed/misc.c
index 7ee49f5881d1..1b957c6bbe5c 100644
--- a/arch/parisc/boot/compressed/misc.c
+++ b/arch/parisc/boot/compressed/misc.c
@@ -319,7 +319,7 @@ unsigned long decompress_kernel(unsigned int started_wide,

/* Limit memory for bootoader to 1GB */
#define ARTIFICIAL_LIMIT (1*1024*1024*1024)
- free_mem_end_ptr = PAGE0->imm_max_mem;
+ free_mem_end_ptr = PAGE0.imm_max_mem;
if (free_mem_end_ptr > ARTIFICIAL_LIMIT)
free_mem_end_ptr = ARTIFICIAL_LIMIT;

diff --git a/arch/parisc/boot/compressed/vmlinux.lds.S b/arch/parisc/boot/compressed/vmlinux.lds.S
index ab7b43990857..83a1f8f67aba 100644
--- a/arch/parisc/boot/compressed/vmlinux.lds.S
+++ b/arch/parisc/boot/compressed/vmlinux.lds.S
@@ -14,6 +14,9 @@ ENTRY(startup)

SECTIONS
{
+ . = __PAGE_OFFSET;
+ PAGE0 = .;
+
/* palo loads at 0x60000 */
/* loaded kernel will move to 0x10000 */
. = 0xe0000; /* should not overwrite palo code */
diff --git a/arch/parisc/include/asm/page.h b/arch/parisc/include/asm/page.h
index d00313d1274e..7b64c05abd0c 100644
--- a/arch/parisc/include/asm/page.h
+++ b/arch/parisc/include/asm/page.h
@@ -100,6 +100,9 @@ typedef struct __physmem_range {
extern physmem_range_t pmem_ranges[];
extern int npmem_ranges;

+/* Address of PAGE0 is defined in vmlinux.lds.S */
+extern struct zeropage PAGE0;
+
#endif /* !__ASSEMBLY__ */

/* WARNING: The definitions below must match exactly to sizeof(pte_t)
@@ -184,8 +187,6 @@ extern int npmem_ranges;
#include <asm-generic/getorder.h>
#include <asm/pdc.h>

-#define PAGE0 ((struct zeropage *)__PAGE_OFFSET)
-
/* DEFINITION OF THE ZERO-PAGE (PAG0) */
/* based on work by Jason Eckhardt (jason@xxxxxxxxxxx) */

diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 776d624a7207..2e8b6e530c09 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -944,9 +944,9 @@ static __init void qemu_header(void)

pr_info("#define PARISC_PDC_ENTRY_ORG 0x%04lx\n\n",
#ifdef CONFIG_64BIT
- (unsigned long)(PAGE0->mem_pdc_hi) << 32 |
+ (unsigned long)(PAGE0.mem_pdc_hi) << 32 |
#endif
- (unsigned long)PAGE0->mem_pdc);
+ (unsigned long)PAGE0.mem_pdc);

pr_info("#define PARISC_PDC_CACHE_INFO");
p = (unsigned long *) &cache_info;
diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
index 7034227dbdf3..17516de2f191 100644
--- a/arch/parisc/kernel/firmware.c
+++ b/arch/parisc/kernel/firmware.c
@@ -103,10 +103,10 @@ long real64_call(unsigned long function, ...);
long real32_call(unsigned long function, ...);

#ifdef CONFIG_64BIT
-# define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
+# define MEM_PDC (unsigned long)(PAGE0.mem_pdc_hi) << 32 | PAGE0.mem_pdc
# define mem_pdc_call(args...) unlikely(parisc_narrow_firmware) ? real32_call(MEM_PDC, args) : real64_call(MEM_PDC, args)
#else
-# define MEM_PDC (unsigned long)PAGE0->mem_pdc
+# define MEM_PDC (unsigned long)PAGE0.mem_pdc
# define mem_pdc_call(args...) real32_call(MEM_PDC, args)
#endif

@@ -1249,9 +1249,9 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)

print:
spin_lock_irqsave(&pdc_lock, flags);
- real32_call(PAGE0->mem_cons.iodc_io,
- (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
- PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+ real32_call(PAGE0.mem_cons.iodc_io,
+ (unsigned long)PAGE0.mem_cons.hpa, ENTRY_IO_COUT,
+ PAGE0.mem_cons.spa, __pa(PAGE0.mem_cons.dp.layers),
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0);
spin_unlock_irqrestore(&pdc_lock, flags);

@@ -1272,14 +1272,14 @@ int pdc_iodc_getc(void)
unsigned long flags;

/* Bail if no console input device. */
- if (!PAGE0->mem_kbd.iodc_io)
+ if (!PAGE0.mem_kbd.iodc_io)
return 0;

/* wait for a keyboard (rs232)-input */
spin_lock_irqsave(&pdc_lock, flags);
- real32_call(PAGE0->mem_kbd.iodc_io,
- (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
- PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
+ real32_call(PAGE0.mem_kbd.iodc_io,
+ (unsigned long)PAGE0.mem_kbd.hpa, ENTRY_IO_CIN,
+ PAGE0.mem_kbd.spa, __pa(PAGE0.mem_kbd.dp.layers),
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);

ch = *iodc_dbuf;
diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c
index 7ab2f2a54400..13234c663e4b 100644
--- a/arch/parisc/kernel/inventory.c
+++ b/arch/parisc/kernel/inventory.c
@@ -164,7 +164,7 @@ static void __init pagezero_memconfig(void)
* should be done.
*/

- npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT);
+ npages = (PAGE_ALIGN(PAGE0.imm_max_mem) >> PAGE_SHIFT);
set_pmem_entry(pmem_ranges,0UL,npages);
npmem_ranges = 1;
}
@@ -648,8 +648,8 @@ void __init do_device_inventory(void)
struct resource res[3] = {0,};
unsigned int base;

- base = ((unsigned long long) PAGE0->pad0[2] << 32)
- | PAGE0->pad0[3]; /* SeaBIOS stored it here */
+ base = ((unsigned long long) PAGE0.pad0[2] << 32)
+ | PAGE0.pad0[3]; /* SeaBIOS stored it here */

res[0].name = "fw_cfg";
res[0].start = base;
diff --git a/arch/parisc/kernel/kexec.c b/arch/parisc/kernel/kexec.c
index 5eb7f30edc1f..6b39b81a96da 100644
--- a/arch/parisc/kernel/kexec.c
+++ b/arch/parisc/kernel/kexec.c
@@ -96,7 +96,7 @@ void machine_kexec(struct kimage *image)
*(unsigned long *)(virt + kexec_cmdline_offset) = arch->cmdline;
*(unsigned long *)(virt + kexec_initrd_start_offset) = arch->initrd_start;
*(unsigned long *)(virt + kexec_initrd_end_offset) = arch->initrd_end;
- *(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0->mem_free;
+ *(unsigned long *)(virt + kexec_free_mem_offset) = PAGE0.mem_free;

flush_cache_all();
flush_tlb_all();
diff --git a/arch/parisc/kernel/kexec_file.c b/arch/parisc/kernel/kexec_file.c
index 8c534204f0fd..619aeebc5800 100644
--- a/arch/parisc/kernel/kexec_file.c
+++ b/arch/parisc/kernel/kexec_file.c
@@ -61,7 +61,7 @@ static void *elf_load(struct kimage *image, char *kernel_buf,
kbuf.bufsz = kbuf.memsz = ALIGN(cmdline_len, 8);
kbuf.buf_align = PAGE_SIZE;
kbuf.top_down = false;
- kbuf.buf_min = PAGE0->mem_free + PAGE_SIZE;
+ kbuf.buf_min = PAGE0.mem_free + PAGE_SIZE;
kbuf.buf_max = kernel_load_addr;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf);
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 2661cdd256ae..b635294184b9 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -218,8 +218,8 @@ static void pdc_console_init_force(void)
++pdc_console_initialized;

/* If the console is duplex then copy the COUT parameters to CIN. */
- if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
- memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
+ if (PAGE0.mem_cons.cl_class == CL_DUPLEX)
+ memcpy(&PAGE0.mem_kbd, &PAGE0.mem_cons, sizeof(PAGE0.mem_cons));

/* register the pdc console */
register_console(&pdc_cons);
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 1b6129e7d776..7872322336a5 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -234,7 +234,7 @@ void __init collect_boot_cpu_data(void)
cr16_seed = get_cycles();
add_device_randomness(&cr16_seed, sizeof(cr16_seed));

- boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
+ boot_cpu_data.cpu_hz = 100 * PAGE0.mem_10msec; /* Hz of this PARISC */

/* get CPU-Model Information... */
#define p ((unsigned long *)&boot_cpu_data.pdc.model)
diff --git a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
index cceb09855e03..0168f7f83fdb 100644
--- a/arch/parisc/kernel/setup.c
+++ b/arch/parisc/kernel/setup.c
@@ -384,7 +384,7 @@ void __init start_parisc(void)
struct pdc_coproc_cfg coproc_cfg;

/* check QEMU/SeaBIOS marker in PAGE0 */
- running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0);
+ running_on_qemu = (memcmp(&PAGE0.pad0, "SeaBIOS", 8) == 0);

cpunum = smp_processor_id();

diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 9fb1e794831b..00283e41fc7f 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -237,10 +237,10 @@ void __init time_init(void)
{
unsigned long cr16_hz;

- clocktick = (100 * PAGE0->mem_10msec) / HZ;
+ clocktick = (100 * PAGE0.mem_10msec) / HZ;
start_cpu_itimer(); /* get CPU 0 started */

- cr16_hz = 100 * PAGE0->mem_10msec; /* Hz */
+ cr16_hz = 100 * PAGE0.mem_10msec; /* Hz */

/* register as sched_clock source */
sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz);
@@ -277,7 +277,7 @@ static int __init init_cr16_clocksource(void)

/* register at clocksource framework */
clocksource_register_hz(&clocksource_cr16,
- 100 * PAGE0->mem_10msec);
+ 100 * PAGE0.mem_10msec);

return 0;
}
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 2769eb991f58..87abee841182 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -55,6 +55,9 @@ jiffies = jiffies_64;
#endif
SECTIONS
{
+ . = __PAGE_OFFSET;
+ PAGE0 = .;
+
. = KERNEL_BINARY_TEXT_START;

__init_begin = .;
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 3f7d6d5b56ac..733961eb25a1 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -283,7 +283,7 @@ static void __init setup_bootmem(void)

#define PDC_CONSOLE_IO_IODC_SIZE 32768

- memblock_reserve(0UL, (unsigned long)(PAGE0->mem_free +
+ memblock_reserve(0UL, (unsigned long)(PAGE0.mem_free +
PDC_CONSOLE_IO_IODC_SIZE));
memblock_reserve(__pa(KERNEL_BINARY_TEXT_START),
(unsigned long)(_end - KERNEL_BINARY_TEXT_START));
diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
index e60690d38d67..9d4ccb8c75bd 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -1542,7 +1542,7 @@ static void sba_hw_init(struct sba_device *sba_dev)
** o reprogram serial port
** o unblock console output
*/
- if (PAGE0->mem_kbd.cl_class == CL_KEYBD) {
+ if (PAGE0.mem_kbd.cl_class == CL_KEYBD) {
pdc_io_reset_devices();
}

@@ -1550,8 +1550,8 @@ static void sba_hw_init(struct sba_device *sba_dev)


#if 0
-printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
- PAGE0->mem_boot.spa, PAGE0->mem_boot.pad, PAGE0->mem_boot.cl_class);
+printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0.mem_boot.hpa,
+ PAGE0.mem_boot.spa, PAGE0.mem_boot.pad, PAGE0.mem_boot.cl_class);

/*
** Need to deal with DMA from LAN.
@@ -1562,8 +1562,8 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
** mem_boot hpa 0xf4008000 sba 0x0 pad 0x0 cl_class 0x1002
** ARGH! invalid class.
*/
- if ((PAGE0->mem_boot.cl_class != CL_RANDOM)
- && (PAGE0->mem_boot.cl_class != CL_SEQU)) {
+ if ((PAGE0.mem_boot.cl_class != CL_RANDOM)
+ && (PAGE0.mem_boot.cl_class != CL_SEQU)) {
pdc_io_reset();
}
#endif
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index 1b451165311c..d5737d9fa8cf 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -395,7 +395,7 @@ static int __init sticonsole_init(void)
pr_info("sticon: Initializing STI text console.\n");
console_lock();
err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
- PAGE0->mem_cons.cl_class != CL_DUPLEX);
+ PAGE0.mem_cons.cl_class != CL_DUPLEX);
console_unlock();

return err;
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index f869b723494f..a6a6b5503ca1 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -966,7 +966,7 @@ static int __init sticore_pa_init(struct parisc_device *dev)
if (!sti)
sti = sti_try_rom_generic(hpa, hpa, NULL);
if (!sti)
- sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL);
+ sti = sti_try_rom_generic(PAGE0.proc_sti, hpa, NULL);
if (!sti)
return 1;