Bug 178357

Summary: [amd64] [patch] export CPU physical and virtual address sizes in sysctl oids using do_cpuid
Product: Base System Reporter: Sofian Brabez <sbz>
Component: amd64Assignee: freebsd-amd64 (Nobody) <amd64>
Status: Closed FIXED    
Severity: Affects Only Me CC: gonzo, kib
Priority: Normal    
Version: 10.0-CURRENT   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
address_sizes.diff none

Description Sofian Brabez freebsd_committer freebsd_triage 2013-05-05 23:50:00 UTC
This patch export CPU Physical and Virtual address sizes through the sysctl interface
using do_cpuid function.

It also patch the sys/modules/linprocfs module add this information in the
/usr/compat/linux/proc/cpuinfo output like it's done in Linux /proc/cpuinfo.

More details can be found here: http://people.freebsd.org/~sbz/cpu/

Fix: Apply the given patch.
Comment 1 John Baldwin freebsd_committer freebsd_triage 2013-05-20 14:44:17 UTC
> --- address_sizes.diff begins here ---
> Index: amd64/amd64/identcpu.c
> ===================================================================
> --- amd64/amd64/identcpu.c	(revision 250287)
> +++ amd64/amd64/identcpu.c	(working copy)
> @@ -109,6 +109,12 @@
>  SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 
>      &hw_clockrate, 0, "CPU instruction clock rate");
>  
> +SYSCTL_UINT(_machdep, OID_AUTO, cpu_physical_address_bits, CTLFLAG_RD,
> +    &cpu_pma_bits, 0, "CPU physical address bits");
> +
> +SYSCTL_UINT(_machdep, OID_AUTO, cpu_virtual_address_bits, CTLFLAG_RD,
> +    &cpu_vma_bits, 0, "CPU virtual address bits");
> +
>  static eventhandler_tag tsc_post_tag;
>  
>  static char cpu_brand[48];
> @@ -516,6 +522,16 @@
>  	cpu_feature = regs[3];
>  	cpu_feature2 = regs[2];
>  
> +	/* Intel CPUID Specification chapter 5.2.7 
> +	 * eax=0x80000008
> +	 * */
> +	do_cpuid(0x80000008, regs);
> +
> +	/* upper bits are virtual size */
> +	cpu_vma_bits = ((regs[0] >> 8) & 0xFF);
> +	/* lower bits are physical size */
> +	cpu_pma_bits = (regs[0] & 0xFF);
> +
>  	/*
>  	 * Clear "Limit CPUID Maxval" bit and get the largest standard CPUID
>  	 * function number again if it is set from BIOS.  It is necessary
> Index: amd64/amd64/initcpu.c
> ===================================================================
> --- amd64/amd64/initcpu.c	(revision 250287)
> +++ amd64/amd64/initcpu.c	(working copy)
> @@ -66,10 +66,12 @@
>  u_int	cpu_high;		/* Highest arg to CPUID */
>  u_int	cpu_exthigh;		/* Highest arg to extended CPUID */
>  u_int	cpu_id;			/* Stepping ID */
> +u_int	cpu_pma_bits;		/* CPU physical address bits */
>  u_int	cpu_procinfo;		/* HyperThreading Info / Brand Index / CLFUSH 
*/
>  u_int	cpu_procinfo2;		/* Multicore info */
>  char	cpu_vendor[20];		/* CPU Origin code */
>  u_int	cpu_vendor_id;		/* CPU vendor ID */
> +u_int	cpu_vma_bits;		/* CPU virtual address bits */
>  u_int	cpu_fxsr;		/* SSE enabled */
>  u_int	cpu_mxcsr_mask;		/* Valid bits in mxcsr */
>  u_int	cpu_clflush_line_size = 32;
> Index: amd64/include/md_var.h
> ===================================================================
> --- amd64/include/md_var.h	(revision 250287)
> +++ amd64/include/md_var.h	(working copy)
> @@ -54,10 +54,12 @@
>  extern	u_int	cpu_id;
>  extern	u_int	cpu_max_ext_state_size;
>  extern	u_int	cpu_mxcsr_mask;
> +extern u_int	cpu_pma_bits;
>  extern	u_int	cpu_procinfo;
>  extern	u_int	cpu_procinfo2;
>  extern	char	cpu_vendor[];
>  extern	u_int	cpu_vendor_id;
> +extern u_int	cpu_vma_bits;
>  extern	char	ctx_switch_xsave[];
>  extern	char	kstack[];
>  extern	char	sigcode[];
> Index: compat/linprocfs/linprocfs.c
> ===================================================================
> --- compat/linprocfs/linprocfs.c	(revision 250287)
> +++ compat/linprocfs/linprocfs.c	(working copy)
> @@ -310,6 +310,12 @@
>  		    fqmhz, fqkhz, fqmhz, fqkhz);
>  	}
>  
> +	if (cpu_vma_bits != 0 && cpu_vma_bits != 0) {

I think you want s/vma/pma/ here for the first check.

> +		sbuf_printf(sb,
> +		    "address sizes\t: %u bits physical, %u bits virtual\n",
> +		    cpu_pma_bits, cpu_vma_bits);
> +	}
> +
>  	return (0);
>  }
>  #endif /* __i386__ || __amd64__ */

I don't know that we need to create new sysctls for this since userland 
processes can just run cpuid directly.  I would be fine adding this to 
linprocfs however.

I think if we want to start exporting cpuid info via sysctl we should think 
about designing a consistent interface for doing so rather than adding ad-hoc 
sysctls for certain fields.

-- 
John Baldwin
Comment 2 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:00:17 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 3 Oleksandr Tymoshenko freebsd_committer freebsd_triage 2019-01-24 22:27:52 UTC
Sofian, John, are there any plans to work on the proposed patch?

Thanks
Comment 4 Konstantin Belousov freebsd_committer freebsd_triage 2019-01-25 10:08:29 UTC
Exporting CPUID values through sysctl is useless.

Besides that we have cpuctl(4) which exports it using ioctl(2) and accessible by cpucontrol(8).  And we have x86info in ports. So the patch would add yet another way to access something that is readily available as a single instruction.

Note that virtual address width is not used for anything, and will be not until the CPUs with 5-level page tables appear.  When they do, this thing would need completely different treatment at the pmap.
Comment 5 Sofian Brabez freebsd_committer freebsd_triage 2019-01-28 20:53:25 UTC
Hi Oleksandr. Wow 2013, thanks for doing the triage!

As John mentioned, the part about exposing them on linprocfs made sense. Since I verified, it was implemented into sys/compat/linprocfs [1] with r317884 [2] 

As Konstantin mentioned, it might break something in the other tier architectures and it's not really needed as we have already alternatives to gather CPU information. 

Back in 2013, I remember my idea was to expose them through sysctl as MacOSX does under machdep.cpu but we don't have this oid tree in FreeBSD.

I closed it.

[1] https://github.com/freebsd/freebsd/blob/master/sys/compat/linprocfs/linprocfs.c#L298

[2] https://svnweb.freebsd.org/base?view=revision&revision=317884