probe: generic_cpu: read 'cpu architecture'

For ARMv8, 64bit kernel, it seems that the /proc/cpuinfo won't report
"model name".  The "CPU architecture" field seems to be supported.  So a
workaround might be reading this as backup plan.

BUG=b:123880691
TEST=None

Change-Id: I9bd8685c2b6bf384b8094c69b2e133fc4a91079c
Reviewed-on: https://chromium-review.googlesource.com/1480753
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Wei-Han Chen <stimim@chromium.org>
Reviewed-by: Fei Shao <fshao@chromium.org>
diff --git a/py/probe/functions/generic_cpu.py b/py/probe/functions/generic_cpu.py
index 59d9350..3e534b3 100644
--- a/py/probe/functions/generic_cpu.py
+++ b/py/probe/functions/generic_cpu.py
@@ -57,10 +57,11 @@
 
   @classmethod
   def _ProbeArm(cls):
-    # For platforms like arm, it sometimes gives the model name in 'Processor',
-    # and sometimes in 'model name'. But they all give something like 'ARMv7
-    # Processor rev 4 (v71)' only. So to uniquely identify an ARM CPU, we should
-    # use the 'Hardware' field.
+    # For ARM platform, ChromeOS kernel has/had special code to expose fields
+    # like 'model name' or 'Processor' and 'Hardware' field.  However, this
+    # doesn't seem to be available in ARMv8 (and probably all future versions).
+    # In this case, we will use 'CPU architecture' to identify the ARM version.
+
     CPU_INFO_FILE = '/proc/cpuinfo'
     with open(CPU_INFO_FILE, 'r') as f:
       cpuinfo = f.read()
@@ -68,13 +69,28 @@
     def _SearchCPUInfo(regex, name):
       matched = re.search(regex, cpuinfo, re.MULTILINE)
       if matched is None:
-        logging.error('Unable to find "%s" field in %s.', name, CPU_INFO_FILE)
+        logging.warning('Unable to find "%s" field in %s.', name, CPU_INFO_FILE)
         return 'unknown'
       return matched.group(1)
 
+    # For ARMv7, model and hardware should be available.
     model = _SearchCPUInfo(r'^(?:Processor|model name)\s*: (.*)$', 'model')
     hardware = _SearchCPUInfo(r'^Hardware\s*: (.*)$', 'hardware')
+
+    # For ARMv8, there is no model nor hardware, we use 'CPU architecture' as
+    # backup plan.  For an ARM device project (reference board and all follower
+    # devices), all SKUs should be using same ARM CPU.  So we don't really need
+    # detail information.  In the future, we can consider adding other "CPU .*"
+    # fields into model name if we think they are important.
+    architecture = _SearchCPUInfo(r'^CPU architecture\s*: (\d+)$',
+                                  'architecture')
+    if model.strip() == 'unknown' and architecture != 'unknown':
+      model = 'ARMv' + architecture.strip()
+    else:
+      logging.error('Unable to construct "model" of ARM CPU')
+
     cores = process_utils.CheckOutput('nproc', shell=True, log=True)
+
     return {
         'model': model.strip(),
         'cores': cores.strip(),