Re: use x2apic if it is enabled by BIOS

2016-10-17 Thread Mark Kettenis
> Date: Sat, 15 Oct 2016 09:55:05 +0200 (CEST)
> From: s...@openbsd.org
> 
> On Fri, 14 Oct 2016, Mike Larkin wrote:
> 
> > On Fri, Oct 14, 2016 at 04:49:31PM +0900, YASUOKA Masahiko wrote:
> > > Hi,
> > > 
> > > I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> > > machine, our kernel panics with following message.
> > > 
> > >   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> > > 
> > > This seems to happen since x2APIC on the machine is enabled by BIOS
> > > and the kernel doesn't assume that.  The diff makes the kernel use
> > > x2APIC if it is enabled by BIOS.
> > > 
> > > ok?
> > > 
> > 
> > This should go in snaps, or wait for reports from tech@ with test results
> > before it should be committed, IMO. We don't have full support for x2apic,
> > and blindly enabling it like this hoping that the bios set everything up
> > right is bound to be a bad assumption on at least one machine out there.
> 
> As I understand the code, it should only change behavior on systems where 
> x2apic is enabled by the bios. And currently on such systems openbsd will 
> not work anyway, because we then try to use xapic mode without disabling 
> x2apic mode. Or am I missing something?

No, I think you're right and the risk of the diff is low.



Re: use x2apic if it is enabled by BIOS

2016-10-16 Thread YASUOKA Masahiko
Hi,

Thanks your comments,

On Fri, 14 Oct 2016 16:23:40 +0200 (CEST)
s...@openbsd.org wrote:
> On Fri, 14 Oct 2016, YASUOKA Masahiko wrote:
>> I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
>> machine, our kernel panics with following message.
>> 
>>   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
>> 
>> This seems to happen since x2APIC on the machine is enabled by BIOS
>> and the kernel doesn't assume that.  The diff makes the kernel use
>> x2APIC if it is enabled by BIOS.
>> 
>> ok?
> 
> the code looks ok, but ...
(snip)
> ... I would leave the comment here why we don't enable it on all hardware 
> that supports it.

I reverted the comment and also tweaked white space.

Index: sys/arch/amd64/amd64/lapic.c
===
RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
retrieving revision 1.44
diff -u -p -r1.44 lapic.c
--- sys/arch/amd64/amd64/lapic.c22 Jun 2016 01:12:38 -  1.44
+++ sys/arch/amd64/amd64/lapic.c17 Oct 2016 01:24:50 -
@@ -170,59 +170,57 @@ lapic_map(paddr_t lapic_base)
int s;
pt_entry_t *pte;
vaddr_t va;
+   u_int64_t msr;
 
-   /*
-* On real hardware, x2apic must only be enabled if interrupt remapping
-* is also enabled. See 10.12.7 of the SDM vol 3.
-* On hypervisors, this is not necessary. Hypervisors can implement
-* x2apic support even if the host CPU does not support it.
-* Until we support interrupt remapping, use x2apic only if the
-* hypervisor flag is also set.
-*/
-   if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
-   u_int64_t msr;
-
-   disable_intr();
-   s = lapic_tpr;
-
-   msr = rdmsr(MSR_APICBASE);
-   msr |= APICBASE_ENABLE_X2APIC;
-   wrmsr(MSR_APICBASE, msr);
+   disable_intr();
+   s = lapic_tpr;
+
+   msr = rdmsr(MSR_APICBASE);
 
+   if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
+   (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
+   ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
+/*
+ * On real hardware, x2apic must only be enabled if interrupt
+ * remapping is also enabled. See 10.12.7 of the SDM vol 3.
+ * On hypervisors, this is not necessary. Hypervisors can
+ * implement x2apic support even if the host CPU does not
+ * support it.  Until we support interrupt remapping, use
+ * x2apic only if the hypervisor flag is also set or it is
+ * enabled by BIOS.
+ */
+   if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
+   msr |= APICBASE_ENABLE_X2APIC;
+   wrmsr(MSR_APICBASE, msr);
+   }
lapic_readreg = x2apic_readreg;
lapic_writereg = x2apic_writereg;
 #ifdef MULTIPROCESSOR
x86_ipi = x2apic_ipi;
 #endif
x2apic_enabled = 1;
-
codepatch_call(CPTAG_EOI, _eoi);
 
lapic_writereg(LAPIC_TPRI, s);
-   enable_intr();
+   } else {
+   /*
+* Map local apic.  If we have a local apic, it's safe to
+* assume we're on a 486 or better and can use invlpg and
+* non-cacheable PTE's
+*
+* Whap the PTE "by hand" rather than calling pmap_kenter_pa
+* because the latter will attempt to invoke TLB shootdown
+* code just as we might have changed the value of
+* cpu_number()..
+*/
+   va = (vaddr_t)_apic;
+   pte = kvtopte(va);
+   *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
+   invlpg(va);
 
-   return;
+   lapic_tpr = s;
}
 
-   va = (vaddr_t)_apic;
-
-   disable_intr();
-   s = lapic_tpr;
-
-   /*
-* Map local apic.  If we have a local apic, it's safe to assume
-* we're on a 486 or better and can use invlpg and non-cacheable PTE's
-*
-* Whap the PTE "by hand" rather than calling pmap_kenter_pa because
-* the latter will attempt to invoke TLB shootdown code just as we
-* might have changed the value of cpu_number()..
-*/
-
-   pte = kvtopte(va);
-   *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
-   invlpg(va);
-
-   lapic_tpr = s;
enable_intr();
 }
 



Re: use x2apic if it is enabled by BIOS

2016-10-15 Thread Mike Larkin
On Sat, Oct 15, 2016 at 09:55:05AM +0200, s...@openbsd.org wrote:
> 
> 
> On Fri, 14 Oct 2016, Mike Larkin wrote:
> 
> > On Fri, Oct 14, 2016 at 04:49:31PM +0900, YASUOKA Masahiko wrote:
> > > Hi,
> > > 
> > > I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> > > machine, our kernel panics with following message.
> > > 
> > >   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> > > 
> > > This seems to happen since x2APIC on the machine is enabled by BIOS
> > > and the kernel doesn't assume that.  The diff makes the kernel use
> > > x2APIC if it is enabled by BIOS.
> > > 
> > > ok?
> > > 
> > 
> > This should go in snaps, or wait for reports from tech@ with test results
> > before it should be committed, IMO. We don't have full support for x2apic,
> > and blindly enabling it like this hoping that the bios set everything up
> > right is bound to be a bad assumption on at least one machine out there.
> 
> As I understand the code, it should only change behavior on systems where 
> x2apic is enabled by the bios. And currently on such systems openbsd will 
> not work anyway, because we then try to use xapic mode without disabling 
> x2apic mode. Or am I missing something?
> 

I'm just saying it needs to be tested on a bunch of machines to make sure
it doesn't break anything, that's all. We've been burned by these sorts of
changes in the past ("make a fundamental change to get one machine working").

-ml

> Stefan
> 
> > 
> > -ml
> > 
> > > Index: sys/arch/amd64/amd64/lapic.c
> > > ===
> > > RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
> > > retrieving revision 1.44
> > > diff -u -p -r1.44 lapic.c
> > > --- sys/arch/amd64/amd64/lapic.c  22 Jun 2016 01:12:38 -  1.44
> > > +++ sys/arch/amd64/amd64/lapic.c  14 Oct 2016 07:45:50 -
> > > @@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
> > >   int s;
> > >   pt_entry_t *pte;
> > >   vaddr_t va;
> > > + u_int64_t msr;
> > >  
> > > - /*
> > > -  * On real hardware, x2apic must only be enabled if interrupt remapping
> > > -  * is also enabled. See 10.12.7 of the SDM vol 3.
> > > -  * On hypervisors, this is not necessary. Hypervisors can implement
> > > -  * x2apic support even if the host CPU does not support it.
> > > -  * Until we support interrupt remapping, use x2apic only if the
> > > -  * hypervisor flag is also set.
> > > -  */
> > > - if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
> > > - u_int64_t msr;
> > > -
> > > - disable_intr();
> > > - s = lapic_tpr;
> > > -
> > > - msr = rdmsr(MSR_APICBASE);
> > > - msr |= APICBASE_ENABLE_X2APIC;
> > > - wrmsr(MSR_APICBASE, msr);
> > > + disable_intr();
> > > + s = lapic_tpr;
> > > +
> > > + msr = rdmsr(MSR_APICBASE);
> > >  
> > > + if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
> > > + (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
> > > + ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
> > > + /*
> > > +  * If x2APIC is enabled already, use it since it is enabled
> > > +  * by BIOS.  On hypervisor, use it if it exists.
> > > +  */
> > > + if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
> > > + msr |= APICBASE_ENABLE_X2APIC;
> > > + wrmsr(MSR_APICBASE, msr);
> > > + }
> > >   lapic_readreg = x2apic_readreg;
> > >   lapic_writereg = x2apic_writereg;
> > >  #ifdef MULTIPROCESSOR
> > >   x86_ipi = x2apic_ipi;
> > >  #endif
> > >   x2apic_enabled = 1;
> > > -
> > >   codepatch_call(CPTAG_EOI, _eoi);
> > >  
> > >   lapic_writereg(LAPIC_TPRI, s);
> > > - enable_intr();
> > > + } else {
> > > + /*
> > > +  * Map local apic.  If we have a local apic, it's safe to
> > > +  * assume we're on a 486 or better and can use invlpg and
> > > +  * non-cacheable PTE's
> > > +  *
> > > +  * Whap the PTE "by hand" rather than calling pmap_kenter_pa
> > > +  * because the latter will attempt to invoke TLB shootdown
> > > +  * code just as we might have changed the

Re: use x2apic if it is enabled by BIOS

2016-10-15 Thread sf


On Fri, 14 Oct 2016, Mike Larkin wrote:

> On Fri, Oct 14, 2016 at 04:49:31PM +0900, YASUOKA Masahiko wrote:
> > Hi,
> > 
> > I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> > machine, our kernel panics with following message.
> > 
> >   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> > 
> > This seems to happen since x2APIC on the machine is enabled by BIOS
> > and the kernel doesn't assume that.  The diff makes the kernel use
> > x2APIC if it is enabled by BIOS.
> > 
> > ok?
> > 
> 
> This should go in snaps, or wait for reports from tech@ with test results
> before it should be committed, IMO. We don't have full support for x2apic,
> and blindly enabling it like this hoping that the bios set everything up
> right is bound to be a bad assumption on at least one machine out there.

As I understand the code, it should only change behavior on systems where 
x2apic is enabled by the bios. And currently on such systems openbsd will 
not work anyway, because we then try to use xapic mode without disabling 
x2apic mode. Or am I missing something?

Stefan

> 
> -ml
> 
> > Index: sys/arch/amd64/amd64/lapic.c
> > ===
> > RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
> > retrieving revision 1.44
> > diff -u -p -r1.44 lapic.c
> > --- sys/arch/amd64/amd64/lapic.c22 Jun 2016 01:12:38 -  1.44
> > +++ sys/arch/amd64/amd64/lapic.c14 Oct 2016 07:45:50 -
> > @@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
> > int s;
> > pt_entry_t *pte;
> > vaddr_t va;
> > +   u_int64_t msr;
> >  
> > -   /*
> > -* On real hardware, x2apic must only be enabled if interrupt remapping
> > -* is also enabled. See 10.12.7 of the SDM vol 3.
> > -* On hypervisors, this is not necessary. Hypervisors can implement
> > -* x2apic support even if the host CPU does not support it.
> > -* Until we support interrupt remapping, use x2apic only if the
> > -* hypervisor flag is also set.
> > -*/
> > -   if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
> > -   u_int64_t msr;
> > -
> > -   disable_intr();
> > -   s = lapic_tpr;
> > -
> > -   msr = rdmsr(MSR_APICBASE);
> > -   msr |= APICBASE_ENABLE_X2APIC;
> > -   wrmsr(MSR_APICBASE, msr);
> > +   disable_intr();
> > +   s = lapic_tpr;
> > +
> > +   msr = rdmsr(MSR_APICBASE);
> >  
> > +   if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
> > +   (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
> > +   ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
> > +   /*
> > +* If x2APIC is enabled already, use it since it is enabled
> > +* by BIOS.  On hypervisor, use it if it exists.
> > +*/
> > +   if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
> > +   msr |= APICBASE_ENABLE_X2APIC;
> > +   wrmsr(MSR_APICBASE, msr);
> > +   }
> > lapic_readreg = x2apic_readreg;
> > lapic_writereg = x2apic_writereg;
> >  #ifdef MULTIPROCESSOR
> > x86_ipi = x2apic_ipi;
> >  #endif
> > x2apic_enabled = 1;
> > -
> > codepatch_call(CPTAG_EOI, _eoi);
> >  
> > lapic_writereg(LAPIC_TPRI, s);
> > -   enable_intr();
> > +   } else {
> > +   /*
> > +* Map local apic.  If we have a local apic, it's safe to
> > +* assume we're on a 486 or better and can use invlpg and
> > +* non-cacheable PTE's
> > +*
> > +* Whap the PTE "by hand" rather than calling pmap_kenter_pa
> > +* because the latter will attempt to invoke TLB shootdown
> > +* code just as we might have changed the value of
> > +* cpu_number()..
> > +*/
> > +   va = (vaddr_t)_apic;
> > +   pte = kvtopte(va);
> > +   *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> > +   invlpg(va);
> >  
> > -   return;
> > +   lapic_tpr = s;
> > }
> >  
> > -   va = (vaddr_t)_apic;
> > -
> > -   disable_intr();
> > -   s = lapic_tpr;
> > -
> > -   /*
> > -* Map local apic.  If we have a local apic, it's safe to assume
> > -* we're on a 486 or better and can use invlpg and non-cacheable PTE's
> > -*
> > -   

Re: use x2apic if it is enabled by BIOS

2016-10-14 Thread Mike Larkin
On Fri, Oct 14, 2016 at 04:49:31PM +0900, YASUOKA Masahiko wrote:
> Hi,
> 
> I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> machine, our kernel panics with following message.
> 
>   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> 
> This seems to happen since x2APIC on the machine is enabled by BIOS
> and the kernel doesn't assume that.  The diff makes the kernel use
> x2APIC if it is enabled by BIOS.
> 
> ok?
> 

This should go in snaps, or wait for reports from tech@ with test results
before it should be committed, IMO. We don't have full support for x2apic,
and blindly enabling it like this hoping that the bios set everything up
right is bound to be a bad assumption on at least one machine out there.

-ml

> Index: sys/arch/amd64/amd64/lapic.c
> ===
> RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 lapic.c
> --- sys/arch/amd64/amd64/lapic.c  22 Jun 2016 01:12:38 -  1.44
> +++ sys/arch/amd64/amd64/lapic.c  14 Oct 2016 07:45:50 -
> @@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
>   int s;
>   pt_entry_t *pte;
>   vaddr_t va;
> + u_int64_t msr;
>  
> - /*
> -  * On real hardware, x2apic must only be enabled if interrupt remapping
> -  * is also enabled. See 10.12.7 of the SDM vol 3.
> -  * On hypervisors, this is not necessary. Hypervisors can implement
> -  * x2apic support even if the host CPU does not support it.
> -  * Until we support interrupt remapping, use x2apic only if the
> -  * hypervisor flag is also set.
> -  */
> - if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
> - u_int64_t msr;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - msr = rdmsr(MSR_APICBASE);
> - msr |= APICBASE_ENABLE_X2APIC;
> - wrmsr(MSR_APICBASE, msr);
> + disable_intr();
> + s = lapic_tpr;
> +
> + msr = rdmsr(MSR_APICBASE);
>  
> + if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
> + (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
> + ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
> + /*
> +  * If x2APIC is enabled already, use it since it is enabled
> +  * by BIOS.  On hypervisor, use it if it exists.
> +  */
> + if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
> + msr |= APICBASE_ENABLE_X2APIC;
> + wrmsr(MSR_APICBASE, msr);
> + }
>   lapic_readreg = x2apic_readreg;
>   lapic_writereg = x2apic_writereg;
>  #ifdef MULTIPROCESSOR
>   x86_ipi = x2apic_ipi;
>  #endif
>   x2apic_enabled = 1;
> -
>   codepatch_call(CPTAG_EOI, _eoi);
>  
>   lapic_writereg(LAPIC_TPRI, s);
> - enable_intr();
> + } else {
> + /*
> +  * Map local apic.  If we have a local apic, it's safe to
> +  * assume we're on a 486 or better and can use invlpg and
> +  * non-cacheable PTE's
> +  *
> +  * Whap the PTE "by hand" rather than calling pmap_kenter_pa
> +  * because the latter will attempt to invoke TLB shootdown
> +  * code just as we might have changed the value of
> +  * cpu_number()..
> +  */
> + va = (vaddr_t)_apic;
> + pte = kvtopte(va);
> + *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> + invlpg(va);
>  
> - return;
> + lapic_tpr = s;
>   }
>  
> - va = (vaddr_t)_apic;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - /*
> -  * Map local apic.  If we have a local apic, it's safe to assume
> -  * we're on a 486 or better and can use invlpg and non-cacheable PTE's
> -  *
> -  * Whap the PTE "by hand" rather than calling pmap_kenter_pa because
> -  * the latter will attempt to invoke TLB shootdown code just as we
> -  * might have changed the value of cpu_number()..
> -  */
> -
> - pte = kvtopte(va);
> - *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> - invlpg(va);
> -
> - lapic_tpr = s;
>   enable_intr();
> +
> + return;
>  }
>  
>  /*
> 
> OpenBSD 6.0-current (GENERIC.MP) #44: Fri Oct 14 16:32:03 JST 2016
> 
> yasu...@yasuoka-ob1.tokyo.iiji.jp:/source/yasuoka/openbsd/head/git/src/sys/arch/amd64/compile/GENERIC.MP
> real mem = 8207699968 (7827MB)
> avail mem = 7954391

Re: use x2apic if it is enabled by BIOS

2016-10-14 Thread sf
On Fri, 14 Oct 2016, YASUOKA Masahiko wrote:
> I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> machine, our kernel panics with following message.
> 
>   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> 
> This seems to happen since x2APIC on the machine is enabled by BIOS
> and the kernel doesn't assume that.  The diff makes the kernel use
> x2APIC if it is enabled by BIOS.
> 
> ok?

the code looks ok, but ...

> 
> Index: sys/arch/amd64/amd64/lapic.c
> ===
> RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 lapic.c
> --- sys/arch/amd64/amd64/lapic.c  22 Jun 2016 01:12:38 -  1.44
> +++ sys/arch/amd64/amd64/lapic.c  14 Oct 2016 07:45:50 -
> @@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
>   int s;
>   pt_entry_t *pte;
>   vaddr_t va;
> + u_int64_t msr;
>  
> - /*
> -  * On real hardware, x2apic must only be enabled if interrupt remapping
> -  * is also enabled. See 10.12.7 of the SDM vol 3.
> -  * On hypervisors, this is not necessary. Hypervisors can implement
> -  * x2apic support even if the host CPU does not support it.
> -  * Until we support interrupt remapping, use x2apic only if the
> -  * hypervisor flag is also set.
> -  */

... I would leave the comment here why we don't enable it on all hardware 
that supports it.

> - if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
> - u_int64_t msr;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - msr = rdmsr(MSR_APICBASE);
> - msr |= APICBASE_ENABLE_X2APIC;
> - wrmsr(MSR_APICBASE, msr);
> + disable_intr();
> + s = lapic_tpr;
> +
> + msr = rdmsr(MSR_APICBASE);
>  
> + if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
> + (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
> + ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
> + /*
> +  * If x2APIC is enabled already, use it since it is enabled
> +  * by BIOS.  On hypervisor, use it if it exists.
> +  */
> + if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
> + msr |= APICBASE_ENABLE_X2APIC;
> + wrmsr(MSR_APICBASE, msr);
> + }
>   lapic_readreg = x2apic_readreg;
>   lapic_writereg = x2apic_writereg;
>  #ifdef MULTIPROCESSOR
>   x86_ipi = x2apic_ipi;
>  #endif
>   x2apic_enabled = 1;
> -
>   codepatch_call(CPTAG_EOI, _eoi);
>  
>   lapic_writereg(LAPIC_TPRI, s);
> - enable_intr();
> + } else {
> + /*
> +  * Map local apic.  If we have a local apic, it's safe to
> +  * assume we're on a 486 or better and can use invlpg and
> +  * non-cacheable PTE's
> +  *
> +  * Whap the PTE "by hand" rather than calling pmap_kenter_pa
> +  * because the latter will attempt to invoke TLB shootdown
> +  * code just as we might have changed the value of
> +  * cpu_number()..
> +  */
> + va = (vaddr_t)_apic;
> + pte = kvtopte(va);
> + *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> + invlpg(va);
>  
> - return;
> + lapic_tpr = s;
>   }
>  
> - va = (vaddr_t)_apic;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - /*
> -  * Map local apic.  If we have a local apic, it's safe to assume
> -  * we're on a 486 or better and can use invlpg and non-cacheable PTE's
> -  *
> -  * Whap the PTE "by hand" rather than calling pmap_kenter_pa because
> -  * the latter will attempt to invoke TLB shootdown code just as we
> -  * might have changed the value of cpu_number()..
> -  */
> -
> - pte = kvtopte(va);
> - *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> - invlpg(va);
> -
> - lapic_tpr = s;
>   enable_intr();
> +
> + return;
>  }



Re: use x2apic if it is enabled by BIOS

2016-10-14 Thread Stefan Fritsch
On Friday, 14 October 2016 15:48:47 CEST Mark Kettenis wrote:
> > Date: Fri, 14 Oct 2016 16:49:31 +0900 (JST)
> > From: YASUOKA Masahiko <yasu...@openbsd.org>
> > 
> > Hi,
> > 
> > I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> > machine, our kernel panics with following message.
> > 
> >   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> > 
> > This seems to happen since x2APIC on the machine is enabled by BIOS
> > and the kernel doesn't assume that.  The diff makes the kernel use
> > x2APIC if it is enabled by BIOS.
> > 
> > ok?
> 
> is the APICBASE msr available on all amd64 machines?  If not, it will
> need to be protected with a CPUID check.

Yes. I have looked that up before, for its use in the suspend/resume code.

Stefan



Re: use x2apic if it is enabled by BIOS

2016-10-14 Thread Mark Kettenis
> Date: Fri, 14 Oct 2016 16:49:31 +0900 (JST)
> From: YASUOKA Masahiko <yasu...@openbsd.org>
> 
> Hi,
> 
> I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
> machine, our kernel panics with following message.
> 
>   cpu0 at mainbus0panic: cpu at apic id 0 already attached?
> 
> This seems to happen since x2APIC on the machine is enabled by BIOS
> and the kernel doesn't assume that.  The diff makes the kernel use
> x2APIC if it is enabled by BIOS.
> 
> ok?

is the APICBASE msr available on all amd64 machines?  If not, it will
need to be protected with a CPUID check.

> Index: sys/arch/amd64/amd64/lapic.c
> ===
> RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 lapic.c
> --- sys/arch/amd64/amd64/lapic.c  22 Jun 2016 01:12:38 -  1.44
> +++ sys/arch/amd64/amd64/lapic.c  14 Oct 2016 07:45:50 -
> @@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
>   int s;
>   pt_entry_t *pte;
>   vaddr_t va;
> + u_int64_t msr;
>  
> - /*
> -  * On real hardware, x2apic must only be enabled if interrupt remapping
> -  * is also enabled. See 10.12.7 of the SDM vol 3.
> -  * On hypervisors, this is not necessary. Hypervisors can implement
> -  * x2apic support even if the host CPU does not support it.
> -  * Until we support interrupt remapping, use x2apic only if the
> -  * hypervisor flag is also set.
> -  */
> - if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
> - u_int64_t msr;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - msr = rdmsr(MSR_APICBASE);
> - msr |= APICBASE_ENABLE_X2APIC;
> - wrmsr(MSR_APICBASE, msr);
> + disable_intr();
> + s = lapic_tpr;
> +
> + msr = rdmsr(MSR_APICBASE);
>  
> + if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
> + (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
> + ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
> + /*
> +  * If x2APIC is enabled already, use it since it is enabled
> +  * by BIOS.  On hypervisor, use it if it exists.
> +  */
> + if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
> + msr |= APICBASE_ENABLE_X2APIC;
> + wrmsr(MSR_APICBASE, msr);
> + }
>   lapic_readreg = x2apic_readreg;
>   lapic_writereg = x2apic_writereg;
>  #ifdef MULTIPROCESSOR
>   x86_ipi = x2apic_ipi;
>  #endif
>   x2apic_enabled = 1;
> -
>   codepatch_call(CPTAG_EOI, _eoi);
>  
>   lapic_writereg(LAPIC_TPRI, s);
> - enable_intr();
> + } else {
> + /*
> +  * Map local apic.  If we have a local apic, it's safe to
> +  * assume we're on a 486 or better and can use invlpg and
> +  * non-cacheable PTE's
> +  *
> +  * Whap the PTE "by hand" rather than calling pmap_kenter_pa
> +  * because the latter will attempt to invoke TLB shootdown
> +  * code just as we might have changed the value of
> +  * cpu_number()..
> +  */
> + va = (vaddr_t)_apic;
> + pte = kvtopte(va);
> + *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> + invlpg(va);
>  
> - return;
> + lapic_tpr = s;
>   }
>  
> - va = (vaddr_t)_apic;
> -
> - disable_intr();
> - s = lapic_tpr;
> -
> - /*
> -  * Map local apic.  If we have a local apic, it's safe to assume
> -  * we're on a 486 or better and can use invlpg and non-cacheable PTE's
> -  *
> -  * Whap the PTE "by hand" rather than calling pmap_kenter_pa because
> -  * the latter will attempt to invoke TLB shootdown code just as we
> -  * might have changed the value of cpu_number()..
> -  */
> -
> - pte = kvtopte(va);
> - *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
> - invlpg(va);
> -
> - lapic_tpr = s;
>   enable_intr();
> +
> + return;
>  }
>  
>  /*
> 
> OpenBSD 6.0-current (GENERIC.MP) #44: Fri Oct 14 16:32:03 JST 2016
> 
> yasu...@yasuoka-ob1.tokyo.iiji.jp:/source/yasuoka/openbsd/head/git/src/sys/arch/amd64/compile/GENERIC.MP
> real mem = 8207699968 (7827MB)
> avail mem = 7954391040 (7585MB)
> mpath0 at root
> scsibus0 at mpath0: 256 targets
> mainbus0 at root
> bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x7f92b000 

use x2apic if it is enabled by BIOS

2016-10-14 Thread YASUOKA Masahiko
Hi,

I'm working on NEC Express5800/R110h-1 (dmesg is attached).  On this
machine, our kernel panics with following message.

  cpu0 at mainbus0panic: cpu at apic id 0 already attached?

This seems to happen since x2APIC on the machine is enabled by BIOS
and the kernel doesn't assume that.  The diff makes the kernel use
x2APIC if it is enabled by BIOS.

ok?

Index: sys/arch/amd64/amd64/lapic.c
===
RCS file: /cvs/src/sys/arch/amd64/amd64/lapic.c,v
retrieving revision 1.44
diff -u -p -r1.44 lapic.c
--- sys/arch/amd64/amd64/lapic.c22 Jun 2016 01:12:38 -  1.44
+++ sys/arch/amd64/amd64/lapic.c14 Oct 2016 07:45:50 -
@@ -170,60 +170,55 @@ lapic_map(paddr_t lapic_base)
int s;
pt_entry_t *pte;
vaddr_t va;
+   u_int64_t msr;
 
-   /*
-* On real hardware, x2apic must only be enabled if interrupt remapping
-* is also enabled. See 10.12.7 of the SDM vol 3.
-* On hypervisors, this is not necessary. Hypervisors can implement
-* x2apic support even if the host CPU does not support it.
-* Until we support interrupt remapping, use x2apic only if the
-* hypervisor flag is also set.
-*/
-   if ((cpu_ecxfeature_X2APIC) && (cpu_ecxfeature_HV)) {
-   u_int64_t msr;
-
-   disable_intr();
-   s = lapic_tpr;
-
-   msr = rdmsr(MSR_APICBASE);
-   msr |= APICBASE_ENABLE_X2APIC;
-   wrmsr(MSR_APICBASE, msr);
+   disable_intr();
+   s = lapic_tpr;
+
+   msr = rdmsr(MSR_APICBASE);
 
+   if (ISSET(msr, APICBASE_ENABLE_X2APIC) ||
+   (ISSET(cpu_ecxfeature, CPUIDECX_HV) &&
+   ISSET(cpu_ecxfeature, CPUIDECX_X2APIC))) {
+   /*
+* If x2APIC is enabled already, use it since it is enabled
+* by BIOS.  On hypervisor, use it if it exists.
+*/
+   if (!ISSET(msr, APICBASE_ENABLE_X2APIC)) {
+   msr |= APICBASE_ENABLE_X2APIC;
+   wrmsr(MSR_APICBASE, msr);
+   }
lapic_readreg = x2apic_readreg;
lapic_writereg = x2apic_writereg;
 #ifdef MULTIPROCESSOR
x86_ipi = x2apic_ipi;
 #endif
x2apic_enabled = 1;
-
codepatch_call(CPTAG_EOI, _eoi);
 
lapic_writereg(LAPIC_TPRI, s);
-   enable_intr();
+   } else {
+   /*
+* Map local apic.  If we have a local apic, it's safe to
+* assume we're on a 486 or better and can use invlpg and
+* non-cacheable PTE's
+*
+* Whap the PTE "by hand" rather than calling pmap_kenter_pa
+* because the latter will attempt to invoke TLB shootdown
+* code just as we might have changed the value of
+* cpu_number()..
+*/
+   va = (vaddr_t)_apic;
+   pte = kvtopte(va);
+   *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
+   invlpg(va);
 
-   return;
+   lapic_tpr = s;
}
 
-   va = (vaddr_t)_apic;
-
-   disable_intr();
-   s = lapic_tpr;
-
-   /*
-* Map local apic.  If we have a local apic, it's safe to assume
-* we're on a 486 or better and can use invlpg and non-cacheable PTE's
-*
-* Whap the PTE "by hand" rather than calling pmap_kenter_pa because
-* the latter will attempt to invoke TLB shootdown code just as we
-* might have changed the value of cpu_number()..
-*/
-
-   pte = kvtopte(va);
-   *pte = lapic_base | PG_RW | PG_V | PG_N | PG_G | pg_nx;
-   invlpg(va);
-
-   lapic_tpr = s;
enable_intr();
+
+   return;
 }
 
 /*

OpenBSD 6.0-current (GENERIC.MP) #44: Fri Oct 14 16:32:03 JST 2016

yasu...@yasuoka-ob1.tokyo.iiji.jp:/source/yasuoka/openbsd/head/git/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 8207699968 (7827MB)
avail mem = 7954391040 (7585MB)
mpath0 at root
scsibus0 at mpath0: 256 targets
mainbus0 at root
bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x7f92b000 (60 entries)
bios0: vendor American Megatrends Inc. version "5.0.4012" date 06/15/2016
bios0: NEC Express5800/R110h-1 [N8100-2316Y]
acpi0 at bios0: rev 2
acpi0: sleep states S0 S4 S5
acpi0: tables DSDT FACP APIC FIDT MCFG HPET SSDT SSDT SSDT SSDT SPCR DMAR BERT
acpi0: wakeup devices PEGP(S4) PEG0(S4) PEG1(S4) PEG2(S4) PXSX(S4) RP17(S4) 
PXSX(S4) RP18(S4) PXSX(S4) RP19(S4) PXSX(S4) RP20(S4) PXSX(S4) RP01(S4) 
PXSX(S4) RP02(S4) [...]
acpitimer0 at acpi0: 3579545 Hz, 24 bits
acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
cpu0 at mainbus0: apid 0 (boot processor)
cpu0: Intel(R) Xeon(R) CPU E3-1220 v5 @ 3.00GHz, 3301.20 MHz
cpu0: 
FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,