[RFC PATCH v2 09/13] x86/um/vdso: nommu: vdso memory update

Hajime Tazaki thehajime at gmail.com
Wed Nov 27 15:23:15 PST 2024


Thanks Benjamin,

On Wed, 27 Nov 2024 19:36:44 +0900,
Benjamin Berg wrote:

> > @@ -51,9 +65,15 @@ __kernel_old_time_t
> > __vdso_time(__kernel_old_time_t *t)
> >  {
> >  	long secs;
> >  
> > +#ifdef CONFIG_MMU
> >  	asm volatile("syscall"
> >  		: "=a" (secs)
> >  		: "0" (__NR_time), "D" (t) : "cc", "r11", "cx",
> > "memory");
> > +#else
> > +	asm("call *%1"
> > +		: "=a" (secs)
> > +		: "0" ((unsigned long)__NR_time), "D" (t) : "cc",
> > "r11", "cx", "memory");
> > +#endif
> 
> Maybe introduce a macro for "syscall" vs. "call *%1"? The parameters
> should be identical in both cases.

I think it's nice to clean up this part.

> The "call" could probably even jump
> to the end of the NOP ramp directly in this case.

ah, that would be a bit of speed ups.
confirmed that it works.  I'll update it if the code readability
doesn't become worse.

> Though maybe I am missing something with the "(unsigned long)" cast?

without this, gcc says

  CC      arch/x86/um/vdso/um_vdso.o
../arch/x86/um/vdso/um_vdso.c: Assembler messages:
../arch/x86/um/vdso/um_vdso.c:50: Error: operand size mismatch for `call'

so the cast intended to silence it.

but if I changed the constraint like below, the error is gone.

-		: "0" ((unsigned long)__NR_time), "D" (t) : "cc",
+		: "a" (__NR_time), "D" (t) : "cc",

I will clean it up as well.

> >  	return secs;
> >  }
> > diff --git a/arch/x86/um/vdso/vma.c b/arch/x86/um/vdso/vma.c
> > index f238f7b33cdd..83c861e2a815 100644
> > --- a/arch/x86/um/vdso/vma.c
> > +++ b/arch/x86/um/vdso/vma.c
> > @@ -9,6 +9,7 @@
> >  #include <asm/page.h>
> >  #include <asm/elf.h>
> >  #include <linux/init.h>
> > +#include <os.h>
> >  
> >  static unsigned int __read_mostly vdso_enabled = 1;
> >  unsigned long um_vdso_addr;
> > @@ -24,7 +25,9 @@ static int __init init_vdso(void)
> >  
> >  	BUG_ON(vdso_end - vdso_start > PAGE_SIZE);
> >  
> > +#ifdef CONFIG_MMU
> >  	um_vdso_addr = task_size - PAGE_SIZE;
> > +#endif
> >  
> >  	vdsop = kmalloc(sizeof(struct page *), GFP_KERNEL);
> >  	if (!vdsop)
> > @@ -40,6 +43,15 @@ static int __init init_vdso(void)
> >  	copy_page(page_address(um_vdso), vdso_start);
> >  	*vdsop = um_vdso;
> >  
> > +#ifndef CONFIG_MMU
> > +	/* this is fine with NOMMU as everything is accessible */
> > +	um_vdso_addr = (unsigned long)page_address(um_vdso);
> > +	os_protect_memory((void *)um_vdso_addr, vdso_end -
> > vdso_start, 1, 1, 1);
> 
> I think this should be "1, 0, 1", i.e. we shouldn't enable write
> access.

not sure if this relates to but with PROT_WRITE off I cannot put a
breakpoint with gdb on vdso area.  normal execution (without gdb)
looks fine.


-- Hajime



More information about the linux-um mailing list