[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2-ish] x86/boot: Factor move_xen() out of __start_xen()
On 20.12.2022 21:56, Andrew Cooper wrote: > On 20/12/2022 1:51 pm, Jan Beulich wrote: >> On 16.12.2022 21:17, Andrew Cooper wrote: >>> + "mov %[cr4], %%cr4\n\t" /* CR4.PGE = 1 */ >>> + : [cr4] "=&a" (tmp) /* Could be "r", but "a" makes better asm */ >>> + : [cr3] "r" (__pa(idle_pg_table)), >>> + [pge] "i" (X86_CR4_PGE) >>> + : "memory" ); >> The removed stack copying worries me, to be honest. Yes, for local >> variables of ours it doesn't matter because they are about to go out >> of scope. But what if the compiler instantiates any for its own use, >> e.g. ... >> >>> + /* >>> + * End of the critical region. Updates to locals and globals now work >>> as >>> + * expected. >>> + * >>> + * Updates to local variables which have been spilled to the stack >>> since >>> + * the memcpy() have been lost. But we don't care, because they're all >>> + * going out of scope imminently. >>> + */ >>> + >>> + printk("New Xen image base address: %#lx\n", xen_phys_start); >> ... the result of the address calculation for the string literal >> here? Such auxiliary calculations can happen at any point in the >> function, and won't necessarily (hence the example chosen) become >> impossible for the compiler to do with the memory clobber in the >> asm(). And while the string literal's address is likely cheap >> enough to calculate right in the function invocation sequence (and >> an option would also be to retain the printk() in the caller), >> other instrumentation options could be undermined by this as well. > > Right now, the compiler is free to calculate the address of the string > literal in a register, and move it the other side of the TLB flush. > This will work just fine. > > However, the compiler cannot now, or ever in the future, spill such a > calculation to the stack. I'm afraid the compiler's view at things is different: Whatever it puts on the stack is viewed as virtual registers, unaffected by a memory clobber (of course there can be effects resulting from uses of named variables). Look at -O3 output of gcc12 (which is what I happened to play with; I don't think it's overly version dependent) for this (clearly contrived) piece of code: int __attribute__((const)) calc(int); int test(int i) { int j = calc(i); asm("nopl %0" : "+m" (j)); asm("nopq %%rsp" ::: "memory", "ax", "cx", "dx", "bx", "bp", "si", "di", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"); j = calc(i); asm("nopl %0" :: "m" (j)); return j; } It instantiates a local on the stack for the result of calc(); it does not re-invoke calc() a 2nd time. Which means the memory clobber in the middle asm() does not affect that (and by implication: any) stack slot. Using godbolt I can also see that clang15 agrees with gcc12 in this regard. I didn't bother trying other versions. > Whether it's spelt "memory", or something else in the future, OSes > really do genuinely need a way of telling the compiler "you literally > cannot move anything the other side of this asm()", because otherwise > malfunctions will occur. Something like this may indeed be desirable in situations like this one, but I don't think such a construct exists. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |