paravirt.h header
Subsystems (2)
PATCH 1/2 paravirt.h header
OK, this is the revised paravirt.h (Andi has seen this before), then the second is the binary patching stuff. More things get added to the paravirt struct in future patches, but this basic stuff hasn't changed for some time.
====
This patch does the dumbest possible replacement of paravirtualized
instructions: calls through a "paravirt_ops" structure. Currently these are function implementations of native hardware: hypervisors will override the ops structure with their own variants.
All the pv-ops functions are declared "fastcall" so that a specific register-based ABI is used, to make inlining assember easier.
--- arch/i386/Kconfig | 11 + arch/i386/kernel/Makefile | 1 arch/i386/kernel/asm-offsets.c | 8 arch/i386/kernel/entry.S | 9 arch/i386/kernel/paravirt.c | 392 ++++++++++++++++++++++++++++++++++++++ include/asm-i386/msr.h | 5 include/asm-i386/paravirt.h | 226 +++++++++++++++++++++ include/asm-i386/paravirt_desc.h | 5 8 files changed, 657 insertions(+)
===================================================================
arch/i386/Kconfig +11 -0
@@ -180,6 +180,17 @@ config X86_ES7000 should say N here. endchoice + +config PARAVIRT + bool "Paravirtualization support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Paravirtualization is a way of running multiple instances of + Linux on the same machine, under a hypervisor. This option + changes the kernel so it can modify itself when it is run + under a hypervisor, improving performance significantly. + However, when run without a hypervisor the kernel is + theoretically slower. If in doubt, say N. config ACPI_SRAT bool
===================================================================
arch/i386/kernel/Makefile +1 -0
@@ -40,6 +40,7 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_AUDIT) += audit.o +obj-$(CONFIG_PARAVIRT) += paravirt.o EXTRA_AFLAGS := -traditional
===================================================================
arch/i386/kernel/asm-offsets.c +8 -0
@@ -15,6 +15,7 @@#include <asm/processor.h> #include <asm/thread_info.h> #include <asm/elf.h> +#include <asm/paravirt.h> #define DEFINE (sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -74,4 +75,11 @@ void foo(void)DEFINE (VDSO_PRELINK ,VDSO_PRELINK );OFFSET (crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); +#ifdef CONFIG_PARAVIRT +OFFSET (PARAVIRT_irq_disable, paravirt_ops, irq_disable); +OFFSET (PARAVIRT_irq_enable, paravirt_ops, irq_enable); +OFFSET (PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); +OFFSET (PARAVIRT_iret, paravirt_ops, iret); +OFFSET (PARAVIRT_read_cr0, paravirt_ops, read_cr0); +#endif }
===================================================================
arch/i386/kernel/entry.S +9 -0
@@ -803,6 +803,15 @@ 1: INTERRUPT_RETURN .long 1b,iret_exc .previous +#ifdef CONFIG_PARAVIRT +ENTRY(nopara_iret) + iret + +ENTRY(nopara_irq_enable_sysexit) + sti + sysexit +#endif + KPROBE_ENTRY(int3) RING0_INT_FRAME pushl $-1 # mark this as an int
===================================================================
include/asm-i386/msr.h +5 -0
@@ -1,5 +1,9 @@#ifndef __ASM_MSR_H#define __ASM_MSR_H + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else /* * Access to machine-specific registers (available on 586 and better only)
@@ -77,6 +81,7 @@ static inline void wrmsrl (unsigned long __asm__ __volatile__("rdpmc" \ :"=a" (low),"=d" (high) \ : "c" (counter)) +#endif /* !CONFIG_PARAVIRT */ /* symbolic names for some interesting MSRs */ /* Intel defined MSRs. */
===================================================================
include/asm-i386/paravirt.h +226 -0
232 lines not on this page · raw message
===================================================================
include/asm-i386/paravirt_desc.h +4 -0
@@ -1,6 +1,10 @@#ifndef __ASM_PARAVIRT_DESC_H#define __ASM_PARAVIRT_DESC_H/* A separate header because they need processor.h, which needs paravirt.h */ +#ifndef CONFIG_PARAVIRT #include <asm/no_paravirt_desc.h> +#else +#include <asm/paravirt.h> +#endif #endif /* __ASM_PARAVIRT_DESC_H */
===================================================================
arch/i386/kernel/paravirt.c new file +382 -0
382 lines not on this page · raw message
Signature · 1 line
Help! Save Australia from the worst of the DMCA: http://linux.org.au/law
PATCH 2/2 paravirt inline patching
(And Andi's request, I drew out the noop-writing part of alternative.c, but unfortunately not much else can be shared.)
===
It turns out that the most called ops, by several orders of magnitude, are the interrupt manipulation ops. These are obvious candidates for patching, so mark them up and create infrastructure for it.
The method used is that the ops structure has a patch function, which is called for each place which needs to be patched: this returns a number of instructions (the rest are NOP-padded).
Usually we can spare a register (%eax) for the binary patched code to use, but in a couple of critical places in entry.S we can't: we make the clobbers explicit at the call site, and manually clobber the allowed registers in debug mode as an extra check.
===================================================================
arch/i386/kernel/alternative.c +59 -12
@@ -123,6 +123,20 @@ static unsigned char** find_nop_table(vo#endif /* CONFIG_X86_64 */ +static void nop_out (void *insns,unsigned int len) +{ +unsigned char **noptable =find_nop_table (); + +while (len >0 ) { +unsigned int noplen = len; +if (noplen >ASM_NOP_MAX ) + noplen =ASM_NOP_MAX ; +memcpy (insns, noptable[noplen], noplen); + insns += noplen; + len -= noplen; + } +} +extern struct alt_instr __alt_instructions[], __alt_instructions_end[];extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];extern u8 *__smp_locks[], *__smp_locks_end[];
@@ -137,10 +151,9 @@ extern u8 __smp_alt_begin[], __smp_alt_evoid apply_alternatives (struct alt_instr *start,struct alt_instr *end) { -unsigned char **noptable =find_nop_table ();struct alt_instr *a;u8 *instr; -int diff, i, k; +int diff;DPRINTK ("%s: alt table %p -> %p\n" , __FUNCTION__, start, end);for (a = start; a < end; a++) {
@@ -158,13 +171,7 @@ void apply_alternatives(struct alt_instr#endif memcpy (instr, a->replacement, a->replacementlen); diff = a->instrlen - a->replacementlen; -/* Pad the rest with nops */ -for (i = a->replacementlen; diff >0 ; diff -= k, i += k) { - k = diff; -if (k >ASM_NOP_MAX ) - k =ASM_NOP_MAX ; -memcpy (a->instr + i, noptable[k], k); - } +nop_out (instr + a->replacementlen, diff); } }
@@ -208,7 +215,6 @@ static void alternatives_smp_lock(u8 **sstatic void alternatives_smp_unlock (u8 **start,u8 **end,u8 *text,u8 *text_end) { -unsigned char **noptable =find_nop_table ();u8 **ptr;for (ptr = start; ptr < end; ptr++) {
@@ -216,7 +222,7 @@ static void alternatives_smp_unlock(u8 *continue ;if (*ptr > text_end)continue ; - **ptr = noptable[1 ][0 ]; +nop_out (*ptr,1 ); }; }
@@ -341,6 +347,45 @@ void alternatives_smp_switch(int smp) }#endif + +#ifdef CONFIG_PARAVIRT +void apply_paravirt (struct paravirt_patch *start,struct paravirt_patch *end) +{ +struct paravirt_patch *p; +int i; + +local_irq_disable (); +for (p = start; p < end; p++) { +unsigned int used; + + used = paravirt_ops.patch (p->instrtype, p->clobbers, p->instr, + p->len); +#ifdef CONFIG_DEBUG_KERNEL +/* Deliberately clobber regs using "not %reg" to find bugs. */ +for (i =0 ; i <3 ; i++) { +if (p->len - used >=2 && (p->clobbers & (1 << i))) { +memcpy (p->instr + used,"\xf7\xd0" ,2 ); + p->instr[used+1 ] |= i; + used +=2 ; + } + } +#endif +/* Pad the rest with nops */ +nop_out (p->instr + used, p->len - used); + } + +/* Sync in case we patched this coming "sti" last. */ +sync_core (); +local_irq_enable (); +} +extern struct paravirt_patch __start_parainstructions[], + __stop_parainstructions[]; +#else +void apply_paravirt (struct paravirt_patch *start,struct paravirt_patch *end) +{ +} +extern struct paravirt_patch *__start_parainstructions, *__stop_parainstructions; +#endif /* CONFIG_PARAVIRT */ void __init alternative_instructions (void ) {
@@ -386,4 +430,6 @@ void __init alternative_instructions(voi alternatives_smp_switch(0); }#endif -} + +apply_paravirt (__start_parainstructions, __stop_parainstructions); +}
===================================================================
arch/i386/kernel/entry.S +13 -13
@@ -77,9 +77,9 @@ VM_MASK = 0x00020000 VM_MASK = 0x00020000 #ifdef CONFIG_PREEMPT -#define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF +#define preempt_stop(clobbers) DISABLE_INTERRUPTS(clobbers); TRACE_IRQS_OFF #else -#define preempt_stop +#define preempt_stop(clobbers) #define resume_kernel restore_nocheck #endif
@@ -223,7 +223,7 @@ ENTRY(ret_from_fork) ALIGN RING0_PTREGS_FRAME ret_from_exception: - preempt_stop + preempt_stop(CLBR_ANY) ret_from_intr: GET_THREAD_INFO(%ebp) check_userspace:
@@ -233,7 +233,7 @@ check_userspace: cmpl $USER_RPL, %eax jb resume_kernel # not returning to v8086 or userspace ENTRY(resume_userspace) - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret movl TI_flags(%ebp), %ecx
@@ -244,7 +244,7 @@ ENTRY(resume_userspace) #ifdef CONFIG_PREEMPT ENTRY(resume_kernel) - DISABLE_INTERRUPTS + DISABLE_INTERRUPTS(CLBR_ANY) cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ? jnz restore_nocheck need_resched:
@@ -272,7 +272,7 @@ sysenter_past_esp: * No need to follow this irqs on/off section: the syscall * disabled irqs and here we enable it straight after entry: */ - ENABLE_INTERRUPTS + ENABLE_INTERRUPTS(CLBR_NONE) pushl $(__USER_DS) CFI_ADJUST_CFA_OFFSET 4 /*CFI_REL_OFFSET ss, 0*/
@@ -317,7 +317,7 @@ 1: movl (%ebp),%ebp jae syscall_badsys call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) - DISABLE_INTERRUPTS + DISABLE_INTERRUPTS(CLBR_ECX|CLBR_EDX) TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx
@@ -352,7 +352,7 @@ syscall_call: call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) # store the return value syscall_exit: - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret TRACE_IRQS_OFF
@@ -381,7 +381,7 @@ 1: INTERRUPT_RETURN .section .fixup,"ax" iret_exc: TRACE_IRQS_ON - ENABLE_INTERRUPTS + ENABLE_INTERRUPTS(CLBR_NONE) pushl $0 # no error code pushl $do_iret_error jmp error_code
@@ -405,7 +405,7 @@ ldt_ss: * dosemu and wine happy. */ subl $8, %esp # reserve space for switch16 pointer CFI_ADJUST_CFA_OFFSET 8 - DISABLE_INTERRUPTS + DISABLE_INTERRUPTS(CLBR_EAX) TRACE_IRQS_OFF movl %esp, %eax /* Set up the 16bit stack frame with switch32 pointer on top,
@@ -430,7 +430,7 @@ work_pending: jz work_notifysig work_resched: call schedule - DISABLE_INTERRUPTS # make sure we don't miss an interrupt + DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret TRACE_IRQS_OFF
@@ -486,7 +486,7 @@ syscall_exit_work: testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl jz work_pending TRACE_IRQS_ON - ENABLE_INTERRUPTS # could let do_syscall_trace() call + ENABLE_INTERRUPTS(CLBR_ANY) # could let do_syscall_trace() call # schedule() instead movl %esp, %eax movl $1, %edx
@@ -667,7 +667,7 @@ ENTRY(device_not_available) GET_CR0_INTO_EAX testl $0x4, %eax # EM (math emulation bit) jne device_not_available_emulate - preempt_stop + preempt_stop(CLBR_ANY) call math_state_restore jmp ret_from_exception device_not_available_emulate:
===================================================================
arch/i386/kernel/module.c +8 -1
@@ -108,7 +108,8 @@ int module_finalize(const Elf_Ehdr *hdr,const Elf_Shdr *sechdrs, struct module *me) { - const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; + const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, + *para =NULL ;char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
@@ -118,6 +119,8 @@ int module_finalize(const Elf_Ehdr *hdr, alt = s;if (!strcmp (".smp_locks" , secstrings + s->sh_name)) locks= s; +if (!strcmp (".parainstructions" , secstrings + s->sh_name)) + para = s; }if (alt) {
@@ -132,6 +135,10 @@ int module_finalize(const Elf_Ehdr *hdr, lseg, lseg + locks->sh_size, tseg, tseg + text->sh_size); } +if (para) { +void *pseg = (void *)para->sh_addr; +apply_paravirt (pseg, pseg + para->sh_size); + }return 0 ; }
===================================================================
arch/i386/kernel/paravirt.c +44 -0
52 lines not on this page · raw message
===================================================================
arch/i386/kernel/vmlinux.lds.S +6 -0
@@ -152,6 +152,12 @@ SECTIONS .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) { *(.altinstr_replacement) } + . = ALIGN(4); + __start_parainstructions = .; + .parainstructions : AT(ADDR(.parainstructions) - LOAD_OFFSET) { + *(.parainstructions) + } + __stop_parainstructions = .; /* .exit.text is discard at runtime, not link time, to deal with references from .altinstructions and .eh_frame */ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
===================================================================
include/asm-i386/alternative.h +3 -0
@@ -138,4 +138,7 @@ static inline void alternatives_smp_swit#define LOCK_PREFIX ""#endif +struct paravirt_patch ; +void apply_paravirt (struct paravirt_patch *start,struct paravirt_patch *end); +#endif /* _I386_ALTERNATIVE_H */
===================================================================
include/asm-i386/irqflags.h +2 -2
@@ -79,8 +79,8 @@ static inline unsigned long __raw_local_ }#else -#define DISABLE_INTERRUPTS cli -#define ENABLE_INTERRUPTS sti +#define DISABLE_INTERRUPTS (clobbers) cli +#define ENABLE_INTERRUPTS (clobbers) sti#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit#define INTERRUPT_RETURN iret#define GET_CR0_INTO_EAX movl %cr0, %eax
===================================================================
include/asm-i386/paravirt.h +143 -37
207 lines not on this page · raw message
===================================================================
include/asm-i386/spinlock.h +3 -1
@@ -22,6 +22,7 @@#else #define CLI_STRING "cli"#define STI_STRING "sti" +#define CLI_STI_CLOBBERS #endif /* CONFIG_PARAVIRT */ #define __raw_spin_is_locked (x) \
@@ -86,7 +87,8 @@ static inline void __raw_spin_lock_flagsalternative_smp ( __raw_spin_lock_string_flags, __raw_spin_lock_string_up, - "+m" (lock->slock) : "r" (flags) : "memory"); + "+m" (lock->slock) : "r" (flags) + : "memory" CLI_STI_CLOBBERS); }#endif
Signature · 1 line
Help! Save Australia from the worst of the DMCA: http://linux.org.au/law
Re: [PATCH 2/2] paravirt inline patching
Quoted 4 lines · On Tue, 22 Aug 2006 16:12:32 +1000 Rusty Russell <[email protected]> wrote:
It turns out that the most called ops, by several orders of magnitude, are the interrupt manipulation ops. These are obvious candidates for patching, so mark them up and create infrastructure for it.
Quoted 8 lines
The method used is that the ops structure has a patch function, which is called for each place which needs to be patched: this returns a number of instructions (the rest are NOP-padded).
Usually we can spare a register (%eax) for the binary patched code to use, but in a couple of critical places in
entry.Swe can't: we make the clobbers explicit at the call site, and manually clobber the allowed registers in debug mode as an extra check.
Looks good to me.
arch/i386/kernel/alternative.c void alternatives_smp_switch(int smp) · line 378
Quoted 3 lines
arch/i386/kernel/alternative.c +3
-0+ +/* Sync in case we patched this coming "sti" last. */ +sync_core ();
I guess this needs more comments -- in particular that it is only safe because the other CPUs are not executing any of this yet and preempt does synchronize anyways.
-Andi
Quoted 1 line · Rusty Russell
OK, this is the revised
paravirt.h(Andi has seen this before),
No, it wasn't. That was the old patch, which won't apply.
This is the right one (and applied with a little fuzz against rc4-mm2).
Sorry,
Rusty.
Create a paravirt.h header for all the critical operations which need to be replaced with hypervisor calls, and include that instead of defining native operations, when CONFIG_PARAVIRT.
This patch does the dumbest possible replacement of paravirtualized
instructions: calls through a "paravirt_ops" structure. Currently these are function implementations of native hardware: hypervisors will override the ops structure with their own variants.
All the pv-ops functions are declared "fastcall" so that a specific register-based ABI is used, to make inlining assember easier.
===================================================================
arch/i386/Kconfig +11 -0
@@ -179,6 +179,17 @@ config X86_ES7000 should say N here. endchoice + +config PARAVIRT + bool "Paravirtualization support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Paravirtualization is a way of running multiple instances of + Linux on the same machine, under a hypervisor. This option + changes the kernel so it can modify itself when it is run + under a hypervisor, improving performance significantly. + However, when run without a hypervisor the kernel is + theoretically slower. If in doubt, say N. config ACPI_SRAT bool
===================================================================
arch/i386/kernel/Makefile +1 -0
@@ -40,6 +40,7 @@ obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_HPET_TIMER) += hpet.o obj-$(CONFIG_K8_NB) += k8.o obj-$(CONFIG_AUDIT) += audit.o +obj-$(CONFIG_PARAVIRT) += paravirt.o EXTRA_AFLAGS := -traditional
===================================================================
arch/i386/kernel/asm-offsets.c +7 -0
@@ -74,4 +74,11 @@ void foo(void)DEFINE (VDSO_PRELINK ,VDSO_PRELINK );OFFSET (crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); +#ifdef CONFIG_PARAVIRT +OFFSET (PARAVIRT_irq_disable, paravirt_ops, irq_disable); +OFFSET (PARAVIRT_irq_enable, paravirt_ops, irq_enable); +OFFSET (PARAVIRT_irq_enable_sysexit, paravirt_ops, irq_enable_sysexit); +OFFSET (PARAVIRT_iret, paravirt_ops, iret); +OFFSET (PARAVIRT_read_cr0, paravirt_ops, read_cr0); +#endif }
===================================================================
arch/i386/kernel/entry.S +13 -7
@@ -76,13 +76,6 @@ NT_MASK = 0x00004000 NT_MASK = 0x00004000 VM_MASK = 0x00020000 -/* These are replaces for paravirtualization */ -#define DISABLE_INTERRUPTS cli -#define ENABLE_INTERRUPTS sti -#define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit -#define INTERRUPT_RETURN iret -#define GET_CR0_INTO_EAX movl %cr0, %eax - #ifdef CONFIG_PREEMPT #define preempt_stop DISABLE_INTERRUPTS; TRACE_IRQS_OFF #else
@@ -809,6 +802,19 @@ 1: INTERRUPT_RETURN .long 1b,iret_exc .previous +#ifdef CONFIG_PARAVIRT +ENTRY(native_iret) +1: iret +.section __ex_table,"a" + .align 4 + .long 1b,iret_exc +.previous + +ENTRY(native_irq_enable_sysexit) + sti + sysexit +#endif + KPROBE_ENTRY(int3) RING0_INT_FRAME pushl $-1 # mark this as an int
===================================================================
include/asm-i386/desc.h +4 -0
@@ -64,6 +64,9 @@ static inline void pack_gate(__u32 *a, _#define DESCTYPE_DPL3 0x60/* DPL-3 */ #define DESCTYPE_S 0x10/* !system */ +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else #define load_TR_desc () __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))#define load_LDT_desc () __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
@@ -98,6 +101,7 @@ static inline void write_dt_entry(void *#define write_ldt_entry (dt, entry, a, b) write_dt_entry(dt, entry, a, b)#define write_gdt_entry (dt, entry, a, b) write_dt_entry(dt, entry, a, b)#define write_idt_entry (dt, entry, a, b) write_dt_entry(dt, entry, a, b) +#endif /* CONFIG_PARAVIRT */ static inline void _set_gate (int gate,unsigned int type,void *addr,unsigned short seg) {
===================================================================
include/asm-i386/irqflags.h +27 -15
69 lines not on this page · raw message
===================================================================
include/asm-i386/msr.h +5 -0
@@ -1,5 +1,9 @@#ifndef __ASM_MSR_H#define __ASM_MSR_H + +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else /* * Access to machine-specific registers (available on 586 and better only)
@@ -77,6 +81,7 @@ static inline void wrmsrl (unsigned long __asm__ __volatile__("rdpmc" \ :"=a" (low),"=d" (high) \ : "c" (counter)) +#endif /* !CONFIG_PARAVIRT */ /* symbolic names for some interesting MSRs */ /* Intel defined MSRs. */
===================================================================
include/asm-i386/processor.h +31 -27
76 lines not on this page · raw message
===================================================================
include/asm-i386/segment.h +2 -0
@@ -128,5 +128,7 @@#define SEGMENT_LDT 0x4#define SEGMENT_GDT 0x0 +#ifndef CONFIG_PARAVIRT #define get_kernel_rpl () 0#endif +#endif
===================================================================
include/asm-i386/spinlock.h +4 -0
@@ -17,8 +17,12 @@* (the type definitions are in asm/spinlock_types.h) */ +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else #define CLI_STRING "cli"#define STI_STRING "sti" +#endif /* CONFIG_PARAVIRT */ #define __raw_spin_is_locked (x) \ (*(volatile signed char *)(&(x)->slock) <= 0)
===================================================================
include/asm-i386/system.h +12 -8
@@ -82,6 +82,9 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"#define savesegment (seg, value) \ asm volatile("mov %%" #seg ",%0":"=rm" (value)) +#ifdef CONFIG_PARAVIRT +#include <asm/paravirt.h> +#else #define read_cr0 () ({ \ unsigned int __dummy; \ __asm__ __volatile__( \
@@ -133,16 +136,17 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t"#define write_cr4 (x) \ __asm__ __volatile__("movl %0,%%cr4": :"r" (x)) -/* -* Clear and set 'TS' bit respectively -*/ -#define clts () __asm__ __volatile__ ("clts") -#define stts () write_cr0(8 | read_cr0()) - -#endif /* __KERNEL__ */ -#define wbinvd () \ __asm__ __volatile__ ("wbinvd": : :"memory") + +/* Clear the 'TS' bit */ +#define clts () __asm__ __volatile__ ("clts") +#endif /* CONFIG_PARAVIRT */ + +/* Set the 'TS' bit */ +#define stts () write_cr0(8 | read_cr0()) + +#endif /* __KERNEL__ */ static inline unsigned long get_limit (unsigned long segment) {
===================================================================
arch/i386/kernel/paravirt.c new file +367 -0
367 lines not on this page · raw message
===================================================================
include/asm-i386/paravirt.h new file +223 -0
223 lines not on this page · raw message
Signature · 1 line
Help! Save Australia from the worst of the DMCA: http://linux.org.au/law
Quoted 4 lines · On Tue, 22 Aug 2006 15:55:15 +1000 Rusty Russell <[email protected]> wrote:
OK, this is the revised
paravirt.h(Andi has seen this before), then the second is the binary patching stuff. More things get added to the paravirt struct in future patches, but this basic stuff hasn't changed for some time.
Thanks. I plan to revisit this after the .19 merge is done. Currently there is too much noise in the tree and even your tree seems to be still changing too quickly.
The patch looks reasonable, except that you still have far too many of these nasty __s around asm and volatile.
-Andi
Quoted 8 lines · Andi Kleen
Quoted 4 lines · On Tue, 22 Aug 2006 15:55:15 +1000 Rusty Russell <[email protected]> wrote:
OK, this is the revised
paravirt.h(Andi has seen this before), then the second is the binary patching stuff. More things get added to the paravirt struct in future patches, but this basic stuff hasn't changed for some time.
Quoted 6 lines
Thanks. I plan to revisit this after the .19 merge is done. Currently there is too much noise in the tree and even your tree seems to be still changing too quickly.
The patch looks reasonable, except that you still have far too many of these nasty
__saround asm and volatile.
Yes, the correct one I sent out later only has __ in two hunks (old code which I moved): I will go through later and remove them all as a separate patch if this annoys you. AFAICT, everything under #ifdef __KERNEL__ can be de-underscored without any ill effects.
Thanks,
Rusty.
Signature · 1 line
Help! Save Australia from the worst of the DMCA: http://linux.org.au/law