This is the intended use, avoid busy-polling of BIOS PC console if
running on HV. Avoid 100% CPU usage at boot prompt on hypervisors.
Originally I unconditionally reverted the polling part, which was
introduced only for Intel Mac Mini. After brief discussion with mikeb@,
I decided to leave that hack by checking HV bit in CPUID (cpu_ecxfeature).
diff --git a/sys/arch/amd64/stand/libsa/bioscons.c
b/sys/arch/amd64/stand/libsa/bioscons.c
index bdff9a4..fa42751 100644
--- a/sys/arch/amd64/stand/libsa/bioscons.c
+++ b/sys/arch/amd64/stand/libsa/bioscons.c
@@ -30,6 +30,7 @@
#include <machine/biosvar.h>
#include <machine/pio.h>
+#include <machine/specialreg.h>
#include <dev/cons.h>
#include <dev/ic/mc146818reg.h>
@@ -37,7 +38,7 @@
#include <dev/ic/ns16450reg.h>
#include <dev/isa/isareg.h>
-#include <lib/libsa/stand.h>
+#include <libsa.h>
#include "biosdev.h"
@@ -82,14 +83,17 @@ pc_getc(dev_t dev)
return (rv & 0xff);
}
- /*
- * Wait for a character to actually become available. Appears to
- * be necessary on (at least) the Intel Mac Mini.
- */
- do {
- __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
- "0" (0x100) : "%ecx", "%edx", "cc" );
- } while ((rv & 0xff) == 0);
+ if ((cpu_ecxfeature & CPUIDECX_HV) == 0) {
+ /*
+ * Wait for a character to actually become available.
+ * Appears to be necessary on (at least) the Intel Mac
+ * Mini.
+ */
+ do {
+ __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
+ "0" (0x100) : "%ecx", "%edx", "cc" );
+ } while ((rv & 0xff) == 0);
+ }
__asm volatile(DOINT(0x16) : "=a" (rv) : "0" (0x000) :
"%ecx", "%edx", "cc" );
diff --git a/sys/arch/i386/stand/libsa/bioscons.c
b/sys/arch/i386/stand/libsa/bioscons.c
index 028bef3..b53abcf 100644
--- a/sys/arch/i386/stand/libsa/bioscons.c
+++ b/sys/arch/i386/stand/libsa/bioscons.c
@@ -27,15 +27,20 @@
*/
#include <sys/types.h>
+
#include <machine/biosvar.h>
#include <machine/pio.h>
+#include <machine/specialreg.h>
+
#include <dev/isa/isareg.h>
#include <dev/ic/mc146818reg.h>
#include <dev/ic/comreg.h>
#include <dev/ic/ns16450reg.h>
/* #include <i386/isa/nvram.h> */
#include <dev/cons.h>
-#include <lib/libsa/stand.h>
+
+#include <libsa.h>
+
#include "debug.h"
#include "biosdev.h"
@@ -80,14 +85,17 @@ pc_getc(dev_t dev)
return (rv & 0xff);
}
- /*
- * Wait for a character to actually become available. Appears to
- * be necessary on (at least) the Intel Mac Mini.
- */
- do {
- __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
- "0" (0x100) : "%ecx", "%edx", "cc" );
- } while ((rv & 0xff) == 0);
+ if ((cpu_ecxfeature & CPUIDECX_HV) == 0) {
+ /*
+ * Wait for a character to actually become available.
+ * Appears to be necessary on (at least) the Intel Mac
+ * Mini.
+ */
+ do {
+ __asm volatile(DOINT(0x16) "; setnz %b0" : "=a" (rv) :
+ "0" (0x100) : "%ecx", "%edx", "cc" );
+ } while ((rv & 0xff) == 0);
+ }
__asm volatile(DOINT(0x16) : "=a" (rv) : "0" (0x000) :
"%ecx", "%edx", "cc" );
On Thu, Mar 17, 2016 at 02:58:58PM +0900, Masao Uebayashi wrote:
> Factor out CPUID code in mdrandom(), invoke it once, then save the
> result. I'll use it to switch behavior depending on HV or not.
>
> efiboot is not tested.
>
> Comments?
> >From 104cb04bbbd0f7e40758938cc3103b2370a2285c Mon Sep 17 00:00:00 2001
> From: Masao Uebayashi <[email protected]>
> Date: Thu, 10 Mar 2016 21:03:07 +0900
> Subject: [PATCH 1/3] Factor out CPUID instruction in amd64 boot code
>
> ---
> sys/arch/amd64/stand/boot/Makefile | 1 +
> sys/arch/amd64/stand/boot/srt0.S | 1 +
> sys/arch/amd64/stand/cdboot/Makefile | 1 +
> sys/arch/amd64/stand/cdboot/srt0.S | 2 +
> sys/arch/amd64/stand/libsa/cpuid.S | 69
> ++++++++++++++++++++++++++++++++
> sys/arch/amd64/stand/libsa/libsa.h | 7 ++++
> sys/arch/amd64/stand/libsa/random_i386.S | 22 +---------
> sys/arch/amd64/stand/pxeboot/Makefile | 1 +
> sys/arch/amd64/stand/pxeboot/srt0.S | 2 +
> 9 files changed, 86 insertions(+), 20 deletions(-)
> create mode 100644 sys/arch/amd64/stand/libsa/cpuid.S
>
> diff --git a/sys/arch/amd64/stand/boot/Makefile
> b/sys/arch/amd64/stand/boot/Makefile
> index 359ea31..5811646 100644
> --- a/sys/arch/amd64/stand/boot/Makefile
> +++ b/sys/arch/amd64/stand/boot/Makefile
> @@ -26,6 +26,7 @@ SRCS+= boot.c bootarg.c cmd.c vars.c
>
> .PATH: ${SADIR}/libsa
> SRCS+= gidt.S random_i386.S
> +SRCS+= cpuid.S
> SRCS+= cmd_i386.c dev_i386.c exec_i386.c gateA20.c machdep.c
> SRCS+= bioscons.c biosdev.c diskprobe.c memprobe.c time.c
> .if ${SOFTRAID:L} == "yes"
> diff --git a/sys/arch/amd64/stand/boot/srt0.S
> b/sys/arch/amd64/stand/boot/srt0.S
> index 9e1ede6..c2a5b2a 100644
> --- a/sys/arch/amd64/stand/boot/srt0.S
> +++ b/sys/arch/amd64/stand/boot/srt0.S
> @@ -87,6 +87,7 @@ _start:
> rep; stosb
>
> call _ASM_LABEL(pmm_init)
> + call _C_LABEL(initcpuid)
> call _C_LABEL(boot)
>
> jmp _C_LABEL(_rtt)
> diff --git a/sys/arch/amd64/stand/cdboot/Makefile
> b/sys/arch/amd64/stand/cdboot/Makefile
> index 23a261f..04ba1e9 100644
> --- a/sys/arch/amd64/stand/cdboot/Makefile
> +++ b/sys/arch/amd64/stand/cdboot/Makefile
> @@ -19,6 +19,7 @@ BINMODE=644
> SRCS+= machdep.c dev_i386.c exec_i386.c cmd_i386.c
> SRCS+= gidt.S random_i386.S biosdev.c bioscons.c gateA20.c \
> memprobe.c diskprobe.c time.c
> +SRCS+= cpuid.S
> SRCS+= softraid.c
>
> .PATH: ${S}/stand/boot
> diff --git a/sys/arch/amd64/stand/cdboot/srt0.S
> b/sys/arch/amd64/stand/cdboot/srt0.S
> index 82ff009..abe40d4 100644
> --- a/sys/arch/amd64/stand/cdboot/srt0.S
> +++ b/sys/arch/amd64/stand/cdboot/srt0.S
> @@ -177,6 +177,8 @@ relocated:
> movl %eax, _C_LABEL(bios_bootdev)
> movl %eax, _C_LABEL(bios_cddev)
>
> + call _C_LABEL(initcpuid)
> +
> /*
> * Now call "main()".
> *
> diff --git a/sys/arch/amd64/stand/libsa/cpuid.S
> b/sys/arch/amd64/stand/libsa/cpuid.S
> new file mode 100644
> index 0000000..c3ca1ac
> --- /dev/null
> +++ b/sys/arch/amd64/stand/libsa/cpuid.S
> @@ -0,0 +1,69 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2016 Masao Uebayashi <[email protected]>
> + * Copyright (c) 2013 Joel Sing <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <machine/param.h>
> +#include <machine/asm.h>
> +#include <machine/psl.h>
> +#include <machine/specialreg.h>
> +
> + .data
> +
> + .globl _C_LABEL(cpu_id)
> + .globl _C_LABEL(cpu_feature)
> + .globl _C_LABEL(cpu_ebxfeature)
> + .globl _C_LABEL(cpu_ecxfeature)
> +
> +_C_LABEL(cpu_id): .long 0
> +_C_LABEL(cpu_feature): .long 0
> +_C_LABEL(cpu_ebxfeature): .long 0
> +_C_LABEL(cpu_ecxfeature): .long 0
> +
> + .text
> +
> +ENTRY(initcpuid)
> + pushal
> +
> + // See if we have CPU identification.
> + pushfl
> + popl %eax
> + movl %eax, %ecx
> + orl $PSL_ID, %eax
> + pushl %eax
> + popfl
> + pushfl
> + popl %eax
> + pushl %ecx
> + popfl
> + andl $PSL_ID, %eax
> + jz done
> +
> + // CPUID leaf = 1, subleaf = 0
> + movl $1, %eax
> + movl $0, %ecx
> + cpuid
> +
> + movl %eax, _C_LABEL(cpu_id)
> + movl %ebx, _C_LABEL(cpu_ebxfeature)
> + movl %ecx, _C_LABEL(cpu_ecxfeature)
> + movl %edx, _C_LABEL(cpu_feature)
> +
> +done:
> + popal
> + ret
> +END(initcpuid)
> diff --git a/sys/arch/amd64/stand/libsa/libsa.h
> b/sys/arch/amd64/stand/libsa/libsa.h
> index fc65c6f..1934078 100644
> --- a/sys/arch/amd64/stand/libsa/libsa.h
> +++ b/sys/arch/amd64/stand/libsa/libsa.h
> @@ -77,3 +77,10 @@ extern u_int32_t bios_cksumlen;
> #define MACHINE_CMD cmd_machine /* we have i386-specific commands */
>
> #define CHECK_SKIP_CONF check_skip_conf /* we can skip boot.conf with
> Ctrl */
> +
> +/* cpuid.S */
> +void initcpuid(void);
> +extern u_int32_t cpu_id;
> +extern u_int32_t cpu_feature;
> +extern u_int32_t cpu_ebxfeature;
> +extern u_int32_t cpu_ecxfeature;
> diff --git a/sys/arch/amd64/stand/libsa/random_i386.S
> b/sys/arch/amd64/stand/libsa/random_i386.S
> index 5e28b40..9d09379 100644
> --- a/sys/arch/amd64/stand/libsa/random_i386.S
> +++ b/sys/arch/amd64/stand/libsa/random_i386.S
> @@ -28,34 +28,16 @@
> ENTRY(mdrandom)
> pushal
>
> - // See if we have CPU identification.
> - pushfl
> - popl %eax
> - movl %eax, %ecx
> - orl $PSL_ID, %eax
> - pushl %eax
> - popfl
> - pushfl
> - popl %eax
> - pushl %ecx
> - popfl
> - andl $PSL_ID, %eax
> - jz done
> -
> - // CPUID leaf = 1, subleaf = 0
> - movl $1, %eax
> - movl $0, %ecx
> - cpuid
> - movl %edx, %eax
> -
> movl 36(%esp), %ebx
> movl 40(%esp), %edx
> xorl %edi, %edi
>
> + movl _C_LABEL(cpu_ecxfeature), %ecx
> andl $CPUIDECX_RDRAND, %ecx // See if we have rdrand.
> jnz userand
>
> movl %edx, %ecx
> + movl _C_LABEL(cpu_feature), %eax
> andl $CPUID_TSC, %eax // See if we have rdtsc.
> jnz usetsc
>
> diff --git a/sys/arch/amd64/stand/pxeboot/Makefile
> b/sys/arch/amd64/stand/pxeboot/Makefile
> index ddf2880..468c7f0 100644
> --- a/sys/arch/amd64/stand/pxeboot/Makefile
> +++ b/sys/arch/amd64/stand/pxeboot/Makefile
> @@ -20,6 +20,7 @@ BINMODE=644
> SRCS+= machdep.c exec_i386.c cmd_i386.c
> SRCS+= gidt.S random_i386.S biosdev.c bioscons.c gateA20.c \
> memprobe.c diskprobe.c time.c ## biosprobe.c
> +SRCS+= cpuid.S
> SRCS+= pxe.c pxe_call.S pxe_net.c pxe_udp.c
> SRCS+= softraid.c
>
> diff --git a/sys/arch/amd64/stand/pxeboot/srt0.S
> b/sys/arch/amd64/stand/pxeboot/srt0.S
> index 9c9226d..ee79225 100644
> --- a/sys/arch/amd64/stand/pxeboot/srt0.S
> +++ b/sys/arch/amd64/stand/pxeboot/srt0.S
> @@ -172,6 +172,8 @@ relocated:
> movl $pxe_progname, %eax
> movl %eax, progname
>
> + call _C_LABEL(initcpuid)
> +
> /*
> * Now call "main()".
> *
> --
> 2.7.0
>
> >From c3072b7c101bd76d9c76b57bd317ce1829ebb153 Mon Sep 17 00:00:00 2001
> From: Masao Uebayashi <[email protected]>
> Date: Thu, 17 Mar 2016 14:48:20 +0900
> Subject: [PATCH 2/3] Implement CPUID in i386 boot loaders too
>
> ---
> sys/arch/i386/stand/boot/Makefile | 1 +
> sys/arch/i386/stand/boot/srt0.S | 1 +
> sys/arch/i386/stand/cdboot/Makefile | 1 +
> sys/arch/i386/stand/cdboot/srt0.S | 2 ++
> sys/arch/i386/stand/libsa/cpuid.S | 69
> ++++++++++++++++++++++++++++++++++++
> sys/arch/i386/stand/libsa/libsa.h | 7 ++++
> sys/arch/i386/stand/pxeboot/Makefile | 1 +
> sys/arch/i386/stand/pxeboot/srt0.S | 2 ++
> 8 files changed, 84 insertions(+)
> create mode 100644 sys/arch/i386/stand/libsa/cpuid.S
>
> diff --git a/sys/arch/i386/stand/boot/Makefile
> b/sys/arch/i386/stand/boot/Makefile
> index 4339b82..c01c160 100644
> --- a/sys/arch/i386/stand/boot/Makefile
> +++ b/sys/arch/i386/stand/boot/Makefile
> @@ -29,6 +29,7 @@ SRCS+= boot.c bootarg.c cmd.c vars.c
> .PATH: ${SADIR}/libsa
> SRCS+= debug_i386.S
> SRCS+= gidt.S random_i386.S
> +SRCS+= cpuid.S
> SRCS+= apmprobe.c debug.c pciprobe.c ps2probe.c
> SRCS+= cmd_i386.c dev_i386.c exec_i386.c gateA20.c machdep.c
> SRCS+= bioscons.c biosdev.c diskprobe.c memprobe.c time.c
> diff --git a/sys/arch/i386/stand/boot/srt0.S b/sys/arch/i386/stand/boot/srt0.S
> index 868b326..07f4240 100644
> --- a/sys/arch/i386/stand/boot/srt0.S
> +++ b/sys/arch/i386/stand/boot/srt0.S
> @@ -87,6 +87,7 @@ _start:
> rep; stosb
>
> call _ASM_LABEL(pmm_init)
> + call _C_LABEL(initcpuid)
> call _C_LABEL(boot)
>
> jmp _C_LABEL(_rtt)
> diff --git a/sys/arch/i386/stand/cdboot/Makefile
> b/sys/arch/i386/stand/cdboot/Makefile
> index 6306887..a533af4 100644
> --- a/sys/arch/i386/stand/cdboot/Makefile
> +++ b/sys/arch/i386/stand/cdboot/Makefile
> @@ -18,6 +18,7 @@ CLEANFILES+= crt0.o ${PROG}.whole
>
> .PATH: ${SADIR}/libsa
> SRCS+= debug_i386.S gidt.S random_i386.S
> +SRCS+= cpuid.S
> SRCS+= cmd_i386.c dev_i386.c exec_i386.c gateA20.c machdep.c
> SRCS+= apmprobe.c bioscons.c biosdev.c debug.c diskprobe.c memprobe.c \
> pciprobe.c ps2probe.c time.c
> diff --git a/sys/arch/i386/stand/cdboot/srt0.S
> b/sys/arch/i386/stand/cdboot/srt0.S
> index 5a721e2..b9b1a19 100644
> --- a/sys/arch/i386/stand/cdboot/srt0.S
> +++ b/sys/arch/i386/stand/cdboot/srt0.S
> @@ -177,6 +177,8 @@ relocated:
> movl %eax, _C_LABEL(bios_bootdev)
> movl %eax, _C_LABEL(bios_cddev)
>
> + call _C_LABEL(initcpuid)
> +
> /*
> * Now call "main()".
> *
> diff --git a/sys/arch/i386/stand/libsa/cpuid.S
> b/sys/arch/i386/stand/libsa/cpuid.S
> new file mode 100644
> index 0000000..c3ca1ac
> --- /dev/null
> +++ b/sys/arch/i386/stand/libsa/cpuid.S
> @@ -0,0 +1,69 @@
> +/* $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2016 Masao Uebayashi <[email protected]>
> + * Copyright (c) 2013 Joel Sing <[email protected]>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <machine/param.h>
> +#include <machine/asm.h>
> +#include <machine/psl.h>
> +#include <machine/specialreg.h>
> +
> + .data
> +
> + .globl _C_LABEL(cpu_id)
> + .globl _C_LABEL(cpu_feature)
> + .globl _C_LABEL(cpu_ebxfeature)
> + .globl _C_LABEL(cpu_ecxfeature)
> +
> +_C_LABEL(cpu_id): .long 0
> +_C_LABEL(cpu_feature): .long 0
> +_C_LABEL(cpu_ebxfeature): .long 0
> +_C_LABEL(cpu_ecxfeature): .long 0
> +
> + .text
> +
> +ENTRY(initcpuid)
> + pushal
> +
> + // See if we have CPU identification.
> + pushfl
> + popl %eax
> + movl %eax, %ecx
> + orl $PSL_ID, %eax
> + pushl %eax
> + popfl
> + pushfl
> + popl %eax
> + pushl %ecx
> + popfl
> + andl $PSL_ID, %eax
> + jz done
> +
> + // CPUID leaf = 1, subleaf = 0
> + movl $1, %eax
> + movl $0, %ecx
> + cpuid
> +
> + movl %eax, _C_LABEL(cpu_id)
> + movl %ebx, _C_LABEL(cpu_ebxfeature)
> + movl %ecx, _C_LABEL(cpu_ecxfeature)
> + movl %edx, _C_LABEL(cpu_feature)
> +
> +done:
> + popal
> + ret
> +END(initcpuid)
> diff --git a/sys/arch/i386/stand/libsa/libsa.h
> b/sys/arch/i386/stand/libsa/libsa.h
> index 76bf1e0..9539376 100644
> --- a/sys/arch/i386/stand/libsa/libsa.h
> +++ b/sys/arch/i386/stand/libsa/libsa.h
> @@ -81,3 +81,10 @@ extern u_int32_t bios_cksumlen;
> #define MACHINE_CMD cmd_machine /* we have i386-specific commands */
>
> #define CHECK_SKIP_CONF check_skip_conf /* we can skip boot.conf with
> Ctrl */
> +
> +/* cpuid.S */
> +void initcpuid(void);
> +extern u_int32_t cpu_id;
> +extern u_int32_t cpu_feature;
> +extern u_int32_t cpu_ebxfeature;
> +extern u_int32_t cpu_ecxfeature;
> diff --git a/sys/arch/i386/stand/pxeboot/Makefile
> b/sys/arch/i386/stand/pxeboot/Makefile
> index 9227246..f26e020 100644
> --- a/sys/arch/i386/stand/pxeboot/Makefile
> +++ b/sys/arch/i386/stand/pxeboot/Makefile
> @@ -21,6 +21,7 @@ SRCS+= debug_i386.S gidt.S random_i386.S
> SRCS+= cmd_i386.c exec_i386.c gateA20.c machdep.c
> SRCS+= apmprobe.c bioscons.c biosdev.c debug.c diskprobe.c memprobe.c \
> pciprobe.c ps2probe.c time.c
> +SRCS+= cpuid.S
> SRCS+= pxe_call.S pxe.c pxe_net.c pxe_udp.c
> SRCS+= softraid.c
>
> diff --git a/sys/arch/i386/stand/pxeboot/srt0.S
> b/sys/arch/i386/stand/pxeboot/srt0.S
> index 16a0313..a62ee6a 100644
> --- a/sys/arch/i386/stand/pxeboot/srt0.S
> +++ b/sys/arch/i386/stand/pxeboot/srt0.S
> @@ -172,6 +172,8 @@ relocated:
> movl $pxe_progname, %eax
> movl %eax, progname
>
> + call _C_LABEL(initcpuid)
> +
> /*
> * Now call "main()".
> *
> --
> 2.7.0
>