mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	Merge commit 'linus' into x86/urgent, to pick up recent x86 changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
		
						commit
						c0c57019a6
					
				
					 576 changed files with 20495 additions and 5125 deletions
				
			
		
							
								
								
									
										
											BIN
										
									
								
								Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Documentation/RCU/Design/Requirements/2013-08-is-it-dead.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 98 KiB | 
							
								
								
									
										374
									
								
								Documentation/RCU/Design/Requirements/GPpartitionReaders1.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										374
									
								
								Documentation/RCU/Design/Requirements/GPpartitionReaders1.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,374 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="447.99197" | ||||
|    height="428.19299" | ||||
|    id="svg2" | ||||
|    version="1.1" | ||||
|    inkscape:version="0.48.3.1 r9886" | ||||
|    sodipodi:docname="GPpartitionReaders1.svg"> | ||||
|   <defs | ||||
|      id="defs4"> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lend" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lend" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3792" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(-1.1,0,0,-1.1,-1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lstart" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lstart" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3789" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(1.1,0,0,1.1,1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|   </defs> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="1.6184291" | ||||
|      inkscape:cx="223.99599" | ||||
|      inkscape:cy="214.0965" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="layer1" | ||||
|      showgrid="false" | ||||
|      inkscape:window-width="979" | ||||
|      inkscape:window-height="836" | ||||
|      inkscape:window-x="571" | ||||
|      inkscape:window-y="335" | ||||
|      inkscape:window-maximized="0" | ||||
|      fit-margin-top="5" | ||||
|      fit-margin-left="5" | ||||
|      fit-margin-right="5" | ||||
|      fit-margin-bottom="5" /> | ||||
|   <metadata | ||||
|      id="metadata7"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Layer 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(-28.441125,-185.60612)"> | ||||
|     <flowRoot | ||||
|        xml:space="preserve" | ||||
|        id="flowRoot2985" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion | ||||
|          id="flowRegion2987"><rect | ||||
|            id="rect2989" | ||||
|            width="82.85714" | ||||
|            height="11.428572" | ||||
|            x="240" | ||||
|            y="492.36218" /></flowRegion><flowPara | ||||
|          id="flowPara2991"></flowPara></flowRoot>    <g | ||||
|        id="g4433" | ||||
|        transform="translate(2,0)"> | ||||
|       <text | ||||
|          sodipodi:linespacing="125%" | ||||
|          id="text2993" | ||||
|          y="-261.66608" | ||||
|          x="412.12299" | ||||
|          style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|          xml:space="preserve" | ||||
|          transform="matrix(0,1,-1,0,0,0)"><tspan | ||||
|            y="-261.66608" | ||||
|            x="412.12299" | ||||
|            id="tspan2995" | ||||
|            sodipodi:role="line">synchronize_rcu()</tspan></text> | ||||
|       <g | ||||
|          id="g4417" | ||||
|          transform="matrix(0,1,-1,0,730.90257,222.4928)"> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)" | ||||
|            d="m 97.580736,477.4048 183.140664,0" | ||||
|            id="path2997" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 96.752718,465.38398 0,22.62742" | ||||
|            id="path4397" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 281.54942,465.38397 0,22.62742" | ||||
|            id="path4397-5" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.04738" | ||||
|        y="268.18076" | ||||
|        id="text4429" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431" | ||||
|          x="112.04738" | ||||
|          y="268.18076">WRITE_ONCE(a, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.04738" | ||||
|        y="439.13766" | ||||
|        id="text4441" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4443" | ||||
|          x="112.04738" | ||||
|          y="439.13766">WRITE_ONCE(b, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="255.60869" | ||||
|        y="309.29346" | ||||
|        id="text4445" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4447" | ||||
|          x="255.60869" | ||||
|          y="309.29346">r1 = READ_ONCE(a);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="255.14423" | ||||
|        y="520.61786" | ||||
|        id="text4449" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4451" | ||||
|          x="255.14423" | ||||
|          y="520.61786">WRITE_ONCE(c, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="384.71124" | ||||
|        id="text4453" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4455" | ||||
|          x="396.10254" | ||||
|          y="384.71124">r2 = READ_ONCE(b);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="582.13617" | ||||
|        id="text4457" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4459" | ||||
|          x="396.10254" | ||||
|          y="582.13617">r3 = READ_ONCE(c);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.08231" | ||||
|        y="213.91006" | ||||
|        id="text4461" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463" | ||||
|          x="112.08231" | ||||
|          y="213.91006">thread0()</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="252.34512" | ||||
|        y="213.91006" | ||||
|        id="text4461-6" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-0" | ||||
|          x="252.34512" | ||||
|          y="213.91006">thread1()</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.42557" | ||||
|        y="213.91006" | ||||
|        id="text4461-2" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-2" | ||||
|          x="396.42557" | ||||
|          y="213.91006">thread2()</tspan></text> | ||||
|     <rect | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="rect4495" | ||||
|        width="436.28488" | ||||
|        height="416.4859" | ||||
|        x="34.648232" | ||||
|        y="191.10612" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 183.14066,191.10612 0,417.193 -0.70711,0" | ||||
|        id="path4497" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 325.13867,191.10612 0,417.193 -0.70711,0" | ||||
|        id="path4497-5" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="111.75929" | ||||
|        y="251.53981" | ||||
|        id="text4429-8" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9" | ||||
|          x="111.75929" | ||||
|          y="251.53981">rcu_read_lock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="367.91556" | ||||
|        id="text4429-8-9" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4" | ||||
|          x="396.10254" | ||||
|          y="367.91556">rcu_read_lock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="597.40289" | ||||
|        id="text4429-8-9-3" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-4" | ||||
|          x="396.10254" | ||||
|          y="597.40289">rcu_read_unlock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="111.75929" | ||||
|        y="453.15311" | ||||
|        id="text4429-8-9-3-1" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-4-6" | ||||
|          x="111.75929" | ||||
|          y="453.15311">rcu_read_unlock();</tspan></text> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|        d="m 33.941125,227.87568 436.284885,0 0,0.7071" | ||||
|        id="path4608" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="394.94427" | ||||
|        y="345.66351" | ||||
|        id="text4648" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650" | ||||
|          x="394.94427" | ||||
|          y="345.66351">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(36.441125,199.60612)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.11968" | ||||
|        y="475.77856" | ||||
|        id="text4648-4" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-4" | ||||
|          x="112.11968" | ||||
|          y="475.77856">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-7" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(-246.38346,329.72117)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-7-7" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(-103.65246,202.90878)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="254.85066" | ||||
|        y="348.96619" | ||||
|        id="text4648-4-3" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-4-5" | ||||
|          x="254.85066" | ||||
|          y="348.96619">QS</tspan></text> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 17 KiB | 
							
								
								
									
										237
									
								
								Documentation/RCU/Design/Requirements/RCUApplicability.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								Documentation/RCU/Design/Requirements/RCUApplicability.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,237 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Creator: fig2dev Version 3.2 Patchlevel 5d --> | ||||
| 
 | ||||
| <!-- CreationDate: Tue Mar  4 18:34:25 2014 --> | ||||
| 
 | ||||
| <!-- Magnification: 3.000 --> | ||||
| 
 | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="1089.1382" | ||||
|    height="668.21368" | ||||
|    viewBox="-2121 -36 14554.634 8876.4061" | ||||
|    id="svg2" | ||||
|    version="1.1" | ||||
|    inkscape:version="0.48.3.1 r9886" | ||||
|    sodipodi:docname="RCUApplicability.svg"> | ||||
|   <metadata | ||||
|      id="metadata40"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <defs | ||||
|      id="defs38" /> | ||||
|   <sodipodi:namedview | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1" | ||||
|      objecttolerance="10" | ||||
|      gridtolerance="10" | ||||
|      guidetolerance="10" | ||||
|      inkscape:pageopacity="0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:window-width="849" | ||||
|      inkscape:window-height="639" | ||||
|      id="namedview36" | ||||
|      showgrid="false" | ||||
|      inkscape:zoom="0.51326165" | ||||
|      inkscape:cx="544.56912" | ||||
|      inkscape:cy="334.10686" | ||||
|      inkscape:window-x="149" | ||||
|      inkscape:window-y="448" | ||||
|      inkscape:window-maximized="0" | ||||
|      inkscape:current-layer="g4" | ||||
|      fit-margin-top="5" | ||||
|      fit-margin-left="5" | ||||
|      fit-margin-right="5" | ||||
|      fit-margin-bottom="5" /> | ||||
|   <g | ||||
|      style="fill:none;stroke-width:0.025in" | ||||
|      id="g4" | ||||
|      transform="translate(-2043.6828,14.791398)"> | ||||
|     <!-- Line: box --> | ||||
|     <rect | ||||
|        x="0" | ||||
|        y="0" | ||||
|        width="14400" | ||||
|        height="8775" | ||||
|        rx="0" | ||||
|        style="fill:#ffa1a1;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter" | ||||
|        id="rect6" /> | ||||
|     <!-- Line: box --> | ||||
|     <rect | ||||
|        x="1350" | ||||
|        y="0" | ||||
|        width="11700" | ||||
|        height="6075" | ||||
|        rx="0" | ||||
|        style="fill:#ffff00;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter" | ||||
|        id="rect8" /> | ||||
|     <!-- Line: box --> | ||||
|     <rect | ||||
|        x="2700" | ||||
|        y="0" | ||||
|        width="9000" | ||||
|        height="4275" | ||||
|        rx="0" | ||||
|        style="fill:#00ff00;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter" | ||||
|        id="rect10" /> | ||||
|     <!-- Line: box --> | ||||
|     <rect | ||||
|        x="4050" | ||||
|        y="0" | ||||
|        width="6300" | ||||
|        height="2475" | ||||
|        rx="0" | ||||
|        style="fill:#87cfff;stroke:#000000;stroke-width:21;stroke-linecap:butt;stroke-linejoin:miter" | ||||
|        id="rect12" /> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="900" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text14" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3017">Read-Mostly, Stale &</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="1350" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text16" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3019">Inconsistent Data OK</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="1800" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text18" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3021">(RCU Works Great!!!)</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="3825" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text20" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3023">(RCU Works Well)</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="3375" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text22" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3025">Read-Mostly, Need Consistent Data</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="5175" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text24" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3027">Read-Write, Need Consistent Data</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="6975" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text26" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|        sodipodi:linespacing="125%">Update-Mostly, Need Consistent Data</text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="5625" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text28" | ||||
|        sodipodi:linespacing="125%" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L"><tspan | ||||
|          style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|          id="tspan3029">(RCU Might Be OK...)</tspan></text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="7875" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text30" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|        sodipodi:linespacing="125%">(1) Provide Existence Guarantees For Update-Friendly Mechanisms</text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="8325" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text32" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|        sodipodi:linespacing="125%">(2) Provide Wait-Free Read-Side Primitives for Real-Time Use)</text> | ||||
|     <!-- Text --> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        x="7200" | ||||
|        y="7425" | ||||
|        font-style="normal" | ||||
|        font-weight="normal" | ||||
|        font-size="324" | ||||
|        id="text34" | ||||
|        style="font-size:427.63009644px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;fill:#000000;font-family:Nimbus Sans L;-inkscape-font-specification:Nimbus Sans L" | ||||
|        sodipodi:linespacing="125%">(RCU is Very Unlikely to be the Right Tool For The Job, But it Can:</text> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 10 KiB | 
							
								
								
									
										639
									
								
								Documentation/RCU/Design/Requirements/ReadersPartitionGP1.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										639
									
								
								Documentation/RCU/Design/Requirements/ReadersPartitionGP1.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,639 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| 
 | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="735.25" | ||||
|    height="516.21875" | ||||
|    id="svg2" | ||||
|    version="1.1" | ||||
|    inkscape:version="0.48.3.1 r9886" | ||||
|    sodipodi:docname="ReadersPartitionGP1.svg"> | ||||
|   <defs | ||||
|      id="defs4"> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lend" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lend" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3792" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(-1.1,0,0,-1.1,-1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lstart" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lstart" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3789" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(1.1,0,0,1.1,1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lstart" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lstart-4" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3789-9" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(1.1,0,0,1.1,1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|     <marker | ||||
|        inkscape:stockid="Arrow2Lend" | ||||
|        orient="auto" | ||||
|        refY="0" | ||||
|        refX="0" | ||||
|        id="Arrow2Lend-4" | ||||
|        style="overflow:visible"> | ||||
|       <path | ||||
|          id="path3792-4" | ||||
|          style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" | ||||
|          d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" | ||||
|          transform="matrix(-1.1,0,0,-1.1,-1.1,0)" | ||||
|          inkscape:connector-curvature="0" /> | ||||
|     </marker> | ||||
|   </defs> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="1.3670394" | ||||
|      inkscape:cx="367.26465" | ||||
|      inkscape:cy="258.46182" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="g4433-6" | ||||
|      showgrid="false" | ||||
|      inkscape:window-width="1351" | ||||
|      inkscape:window-height="836" | ||||
|      inkscape:window-x="438" | ||||
|      inkscape:window-y="335" | ||||
|      inkscape:window-maximized="0" | ||||
|      fit-margin-top="5" | ||||
|      fit-margin-left="5" | ||||
|      fit-margin-right="5" | ||||
|      fit-margin-bottom="5" /> | ||||
|   <metadata | ||||
|      id="metadata7"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title /> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Layer 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(-29.15625,-185.59375)"> | ||||
|     <flowRoot | ||||
|        xml:space="preserve" | ||||
|        id="flowRoot2985" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol"><flowRegion | ||||
|          id="flowRegion2987"><rect | ||||
|            id="rect2989" | ||||
|            width="82.85714" | ||||
|            height="11.428572" | ||||
|            x="240" | ||||
|            y="492.36218" /></flowRegion><flowPara | ||||
|          id="flowPara2991" /></flowRoot>    <g | ||||
|        id="g4433" | ||||
|        transform="translate(2,-12)"> | ||||
|       <text | ||||
|          sodipodi:linespacing="125%" | ||||
|          id="text2993" | ||||
|          y="-261.66608" | ||||
|          x="436.12299" | ||||
|          style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|          xml:space="preserve" | ||||
|          transform="matrix(0,1,-1,0,0,0)"><tspan | ||||
|            y="-261.66608" | ||||
|            x="436.12299" | ||||
|            id="tspan2995" | ||||
|            sodipodi:role="line">synchronize_rcu()</tspan></text> | ||||
|       <g | ||||
|          id="g4417" | ||||
|          transform="matrix(0,1,-1,0,730.90257,222.4928)"> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)" | ||||
|            d="M 97.580736,477.4048 327.57913,476.09759" | ||||
|            id="path2997" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 96.752718,465.38398 0,22.62742" | ||||
|            id="path4397" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 328.40703,465.38397 0,22.62742" | ||||
|            id="path4397-5" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.04738" | ||||
|        y="268.18076" | ||||
|        id="text4429" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431" | ||||
|          x="112.04738" | ||||
|          y="268.18076">WRITE_ONCE(a, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.04738" | ||||
|        y="487.13766" | ||||
|        id="text4441" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4443" | ||||
|          x="112.04738" | ||||
|          y="487.13766">WRITE_ONCE(b, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="255.60869" | ||||
|        y="297.29346" | ||||
|        id="text4445" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4447" | ||||
|          x="255.60869" | ||||
|          y="297.29346">r1 = READ_ONCE(a);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="255.14423" | ||||
|        y="554.61786" | ||||
|        id="text4449" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4451" | ||||
|          x="255.14423" | ||||
|          y="554.61786">WRITE_ONCE(c, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="370.71124" | ||||
|        id="text4453" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4455" | ||||
|          x="396.10254" | ||||
|          y="370.71124">WRITE_ONCE(d, 1);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="572.13617" | ||||
|        id="text4457" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4459" | ||||
|          x="396.10254" | ||||
|          y="572.13617">r2 = READ_ONCE(c);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.08231" | ||||
|        y="213.91006" | ||||
|        id="text4461" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463" | ||||
|          x="112.08231" | ||||
|          y="213.91006">thread0()</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="252.34512" | ||||
|        y="213.91006" | ||||
|        id="text4461-6" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-0" | ||||
|          x="252.34512" | ||||
|          y="213.91006">thread1()</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.42557" | ||||
|        y="213.91006" | ||||
|        id="text4461-2" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-2" | ||||
|          x="396.42557" | ||||
|          y="213.91006">thread2()</tspan></text> | ||||
|     <rect | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="rect4495" | ||||
|        width="724.25244" | ||||
|        height="505.21201" | ||||
|        x="34.648232" | ||||
|        y="191.10612" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 183.14066,191.10612 0,504.24243" | ||||
|        id="path4497" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="cc" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 325.13867,191.10612 0,504.24243" | ||||
|        id="path4497-5" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="cc" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="111.75929" | ||||
|        y="251.53981" | ||||
|        id="text4429-8" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9" | ||||
|          x="111.75929" | ||||
|          y="251.53981">rcu_read_lock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="353.91556" | ||||
|        id="text4429-8-9" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4" | ||||
|          x="396.10254" | ||||
|          y="353.91556">rcu_read_lock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="396.10254" | ||||
|        y="587.40289" | ||||
|        id="text4429-8-9-3" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-4" | ||||
|          x="396.10254" | ||||
|          y="587.40289">rcu_read_unlock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="111.75929" | ||||
|        y="501.15311" | ||||
|        id="text4429-8-9-3-1" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-4-6" | ||||
|          x="111.75929" | ||||
|          y="501.15311">rcu_read_unlock();</tspan></text> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|        d="m 33.941125,227.87568 724.941765,0" | ||||
|        id="path4608" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="cc" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="394.94427" | ||||
|        y="331.66351" | ||||
|        id="text4648" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650" | ||||
|          x="394.94427" | ||||
|          y="331.66351">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(36.441125,185.60612)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="112.11968" | ||||
|        y="523.77856" | ||||
|        id="text4648-4" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-4" | ||||
|          x="112.11968" | ||||
|          y="523.77856">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-7" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(-246.38346,377.72117)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-7-7" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(-103.65246,190.90878)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="254.85066" | ||||
|        y="336.96619" | ||||
|        id="text4648-4-3" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-4-5" | ||||
|          x="254.85066" | ||||
|          y="336.96619">QS</tspan></text> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 470.93311,190.39903 0,504.24243" | ||||
|        id="path4497-5-6" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="cc" /> | ||||
|     <path | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        d="m 616.22755,190.38323 0,504.24243" | ||||
|        id="path4497-5-2" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="cc" /> | ||||
|     <g | ||||
|        id="g4433-6" | ||||
|        transform="translate(288.0964,78.32827)"> | ||||
|       <text | ||||
|          sodipodi:linespacing="125%" | ||||
|          id="text2993-7" | ||||
|          y="-261.66608" | ||||
|          x="440.12299" | ||||
|          style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|          xml:space="preserve" | ||||
|          transform="matrix(0,1,-1,0,0,0)"><tspan | ||||
|            y="-261.66608" | ||||
|            x="440.12299" | ||||
|            id="tspan2995-1" | ||||
|            sodipodi:role="line">synchronize_rcu()</tspan></text> | ||||
|       <g | ||||
|          id="g4417-1" | ||||
|          transform="matrix(0,1,-1,0,730.90257,222.4928)"> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Lstart);marker-end:url(#Arrow2Lend)" | ||||
|            d="M 97.580736,477.4048 328.5624,477.07246" | ||||
|            id="path2997-2" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 96.752718,465.38398 0,22.62742" | ||||
|            id="path4397-3" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|         <path | ||||
|            style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | ||||
|            d="m 329.39039,465.38397 0,22.62742" | ||||
|            id="path4397-5-4" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="cc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="541.70508" | ||||
|        y="387.6217" | ||||
|        id="text4445-0" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4447-5" | ||||
|          x="541.70508" | ||||
|          y="387.6217">r3 = READ_ONCE(d);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="541.2406" | ||||
|        y="646.94611" | ||||
|        id="text4449-6" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4451-6" | ||||
|          x="541.2406" | ||||
|          y="646.94611">WRITE_ONCE(e, 1);</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-7-7-5" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(182.44393,281.23704)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="540.94702" | ||||
|        y="427.29443" | ||||
|        id="text4648-4-3-1" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-4-5-7" | ||||
|          x="540.94702" | ||||
|          y="427.29443">QS</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="686.27747" | ||||
|        y="461.83929" | ||||
|        id="text4453-7" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4455-1" | ||||
|          x="686.27747" | ||||
|          y="461.83929">r4 = READ_ONCE(b);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="686.27747" | ||||
|        y="669.26422" | ||||
|        id="text4457-9" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4459-2" | ||||
|          x="686.27747" | ||||
|          y="669.26422">r5 = READ_ONCE(e);</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="686.27747" | ||||
|        y="445.04358" | ||||
|        id="text4429-8-9-33" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-2" | ||||
|          x="686.27747" | ||||
|          y="445.04358">rcu_read_lock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="686.27747" | ||||
|        y="684.53094" | ||||
|        id="text4429-8-9-3-8" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4431-9-4-4-5" | ||||
|          x="686.27747" | ||||
|          y="684.53094">rcu_read_unlock();</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="685.11914" | ||||
|        y="422.79153" | ||||
|        id="text4648-9" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-7" | ||||
|          x="685.11914" | ||||
|          y="422.79153">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-8" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(326.61602,276.73415)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="397.85934" | ||||
|        y="609.59003" | ||||
|        id="text4648-5" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-77" | ||||
|          x="397.85934" | ||||
|          y="609.59003">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-80" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(39.356201,463.53264)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="256.75986" | ||||
|        y="586.99133" | ||||
|        id="text4648-5-2" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4650-77-7" | ||||
|          x="256.75986" | ||||
|          y="586.99133">QS</tspan></text> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" | ||||
|        id="path4652-80-5" | ||||
|        sodipodi:cx="358.85669" | ||||
|        sodipodi:cy="142.87541" | ||||
|        sodipodi:rx="10.960155" | ||||
|        sodipodi:ry="10.253048" | ||||
|        d="m 358.86939,132.62237 a 10.960155,10.253048 0 1 1 -0.0228,0" | ||||
|        transform="translate(-101.74328,440.93395)" | ||||
|        sodipodi:start="4.7135481" | ||||
|        sodipodi:end="10.994651" | ||||
|        sodipodi:open="true" /> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="546.22791" | ||||
|        y="213.91006" | ||||
|        id="text4461-2-5" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-2-6" | ||||
|          x="546.22791" | ||||
|          y="213.91006">thread3()</tspan></text> | ||||
|     <text | ||||
|        xml:space="preserve" | ||||
|        style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Symbol;-inkscape-font-specification:Symbol" | ||||
|        x="684.00067" | ||||
|        y="213.91006" | ||||
|        id="text4461-2-1" | ||||
|        sodipodi:linespacing="125%"><tspan | ||||
|          sodipodi:role="line" | ||||
|          id="tspan4463-2-0" | ||||
|          x="684.00067" | ||||
|          y="213.91006">thread4()</tspan></text> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 29 KiB | 
							
								
								
									
										2897
									
								
								Documentation/RCU/Design/Requirements/Requirements.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2897
									
								
								Documentation/RCU/Design/Requirements/Requirements.html
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2741
									
								
								Documentation/RCU/Design/Requirements/Requirements.htmlx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2741
									
								
								Documentation/RCU/Design/Requirements/Requirements.htmlx
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										108
									
								
								Documentation/RCU/Design/htmlqqz.sh
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										108
									
								
								Documentation/RCU/Design/htmlqqz.sh
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,108 @@ | |||
| #!/bin/sh | ||||
| # | ||||
| # Usage: sh htmlqqz.sh file | ||||
| # | ||||
| # Extracts and converts quick quizzes in a proto-HTML document file.htmlx. | ||||
| # Commands, all of which must be on a line by themselves: | ||||
| # | ||||
| #	"<p>@@QQ@@": Start of a quick quiz. | ||||
| #	"<p>@@QQA@@": Start of a quick-quiz answer. | ||||
| #	"<p>@@QQE@@": End of a quick-quiz answer, and thus of the quick quiz. | ||||
| #	"<p>@@QQAL@@": Place to put quick-quiz answer list. | ||||
| # | ||||
| # Places the result in file.html. | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 2 of the License, or | ||||
| # (at your option) any later version. | ||||
| # | ||||
| # This program is distributed in the hope that it will be useful, | ||||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| # GNU General Public License for more details. | ||||
| # | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program; if not, you can access it online at | ||||
| # http://www.gnu.org/licenses/gpl-2.0.html. | ||||
| # | ||||
| # Copyright (c) 2013 Paul E. McKenney, IBM Corporation. | ||||
| 
 | ||||
| fn=$1 | ||||
| if test ! -r $fn.htmlx | ||||
| then | ||||
| 	echo "Error: $fn.htmlx unreadable." | ||||
| 	exit 1 | ||||
| fi | ||||
| 
 | ||||
| echo "<!-- DO NOT HAND EDIT. -->" > $fn.html | ||||
| echo "<!-- Instead, edit $fn.htmlx and run 'sh htmlqqz.sh $fn' -->" >> $fn.html | ||||
| awk < $fn.htmlx >> $fn.html ' | ||||
| 
 | ||||
| state == "" && $1 != "<p>@@QQ@@" && $1 != "<p>@@QQAL@@" { | ||||
| 	print $0; | ||||
| 	if ($0 ~ /^<p>@@QQ/) | ||||
| 		print "Bad Quick Quiz command: " NR " (expected <p>@@QQ@@ or <p>@@QQAL@@)." > "/dev/stderr" | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "" && $1 == "<p>@@QQ@@" { | ||||
| 	qqn++; | ||||
| 	qqlineno = NR; | ||||
| 	haveqq = 1; | ||||
| 	state = "qq"; | ||||
| 	print "<p><a name=\"Quick Quiz " qqn "\"><b>Quick Quiz " qqn "</b>:</a>" | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "qq" && $1 != "<p>@@QQA@@" { | ||||
| 	qq[qqn] = qq[qqn] $0 "\n"; | ||||
| 	print $0 | ||||
| 	if ($0 ~ /^<p>@@QQ/) | ||||
| 		print "Bad Quick Quiz command: " NR ". (expected <p>@@QQA@@)" > "/dev/stderr" | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "qq" && $1 == "<p>@@QQA@@" { | ||||
| 	state = "qqa"; | ||||
| 	print "<br><a href=\"#qq" qqn "answer\">Answer</a>" | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "qqa" && $1 != "<p>@@QQE@@" { | ||||
| 	qqa[qqn] = qqa[qqn] $0 "\n"; | ||||
| 	if ($0 ~ /^<p>@@QQ/) | ||||
| 		print "Bad Quick Quiz command: " NR " (expected <p>@@QQE@@)." > "/dev/stderr" | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "qqa" && $1 == "<p>@@QQE@@" { | ||||
| 	state = ""; | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| state == "" && $1 == "<p>@@QQAL@@" { | ||||
| 	haveqq = ""; | ||||
| 	print "<h3><a name=\"Answers to Quick Quizzes\">" | ||||
| 	print "Answers to Quick Quizzes</a></h3>" | ||||
| 	print ""; | ||||
| 	for (i = 1; i <= qqn; i++) { | ||||
| 		print "<a name=\"qq" i "answer\"></a>" | ||||
| 		print "<p><b>Quick Quiz " i "</b>:" | ||||
| 		print qq[i]; | ||||
| 		print ""; | ||||
| 		print "</p><p><b>Answer</b>:" | ||||
| 		print qqa[i]; | ||||
| 		print ""; | ||||
| 		print "</p><p><a href=\"#Quick%20Quiz%20" i "\"><b>Back to Quick Quiz " i "</b>.</a>" | ||||
| 		print ""; | ||||
| 	} | ||||
| 	next; | ||||
| } | ||||
| 
 | ||||
| END { | ||||
| 	if (state != "") | ||||
| 		print "Unterminated Quick Quiz: " qqlineno "." > "/dev/stderr" | ||||
| 	else if (haveqq) | ||||
| 		print "Missing \"<p>@@QQAL@@\", no Quick Quiz." > "/dev/stderr" | ||||
| }' | ||||
|  | @ -50,8 +50,7 @@ prototypes: | |||
| 	int (*rename2) (struct inode *, struct dentry *, | ||||
| 			struct inode *, struct dentry *, unsigned int); | ||||
| 	int (*readlink) (struct dentry *, char __user *,int); | ||||
| 	const char *(*follow_link) (struct dentry *, void **); | ||||
| 	void (*put_link) (struct inode *, void *); | ||||
| 	const char *(*get_link) (struct dentry *, struct inode *, void **); | ||||
| 	void (*truncate) (struct inode *); | ||||
| 	int (*permission) (struct inode *, int, unsigned int); | ||||
| 	int (*get_acl)(struct inode *, int); | ||||
|  | @ -83,8 +82,7 @@ rmdir:		yes (both)	(see below) | |||
| rename:		yes (all)	(see below) | ||||
| rename2:	yes (all)	(see below) | ||||
| readlink:	no | ||||
| follow_link:	no | ||||
| put_link:	no | ||||
| get_link:	no | ||||
| setattr:	yes | ||||
| permission:	no (may not block if called in rcu-walk mode) | ||||
| get_acl:	no | ||||
|  |  | |||
|  | @ -504,3 +504,20 @@ in your dentry operations instead. | |||
| [mandatory] | ||||
| 	__fd_install() & fd_install() can now sleep. Callers should not | ||||
| 	hold a spinlock	or other resources that do not allow a schedule. | ||||
| -- | ||||
| [mandatory] | ||||
| 	any symlink that might use page_follow_link_light/page_put_link() must | ||||
| 	have inode_nohighmem(inode) called before anything might start playing with | ||||
| 	its pagecache. | ||||
| -- | ||||
| [mandatory] | ||||
| 	->follow_link() is replaced with ->get_link(); same API, except that | ||||
| 		* ->get_link() gets inode as a separate argument | ||||
| 		* ->get_link() may be called in RCU mode - in that case NULL | ||||
| 		  dentry is passed | ||||
| -- | ||||
| [mandatory] | ||||
| 	->get_link() gets struct delayed_call *done now, and should do | ||||
| 	set_delayed_call() where it used to set *cookie. | ||||
| 	->put_link() is gone - just give the destructor to set_delayed_call() | ||||
| 	in ->get_link(). | ||||
|  |  | |||
|  | @ -350,8 +350,8 @@ struct inode_operations { | |||
| 	int (*rename2) (struct inode *, struct dentry *, | ||||
| 			struct inode *, struct dentry *, unsigned int); | ||||
| 	int (*readlink) (struct dentry *, char __user *,int); | ||||
| 	const char *(*follow_link) (struct dentry *, void **); | ||||
| 	void (*put_link) (struct inode *, void *); | ||||
| 	const char *(*get_link) (struct dentry *, struct inode *, | ||||
| 				 struct delayed_call *); | ||||
| 	int (*permission) (struct inode *, int); | ||||
| 	int (*get_acl)(struct inode *, int); | ||||
| 	int (*setattr) (struct dentry *, struct iattr *); | ||||
|  | @ -434,20 +434,19 @@ otherwise noted. | |||
|   readlink: called by the readlink(2) system call. Only required if | ||||
| 	you want to support reading symbolic links | ||||
| 
 | ||||
|   follow_link: called by the VFS to follow a symbolic link to the | ||||
|   get_link: called by the VFS to follow a symbolic link to the | ||||
| 	inode it points to.  Only required if you want to support | ||||
| 	symbolic links.  This method returns the symlink body | ||||
| 	to traverse (and possibly resets the current position with | ||||
| 	nd_jump_link()).  If the body won't go away until the inode | ||||
| 	is gone, nothing else is needed; if it needs to be otherwise | ||||
| 	pinned, the data needed to release whatever we'd grabbed | ||||
| 	is to be stored in void * variable passed by address to | ||||
| 	follow_link() instance. | ||||
| 
 | ||||
|   put_link: called by the VFS to release resources allocated by | ||||
| 	follow_link().  The cookie stored by follow_link() is passed | ||||
| 	to this method as the last parameter; only called when | ||||
| 	cookie isn't NULL. | ||||
| 	pinned, arrange for its release by having get_link(..., ..., done) | ||||
| 	do set_delayed_call(done, destructor, argument). | ||||
| 	In that case destructor(argument) will be called once VFS is | ||||
| 	done with the body you've returned. | ||||
| 	May be called in RCU mode; that is indicated by NULL dentry | ||||
| 	argument.  If request can't be handled without leaving RCU mode, | ||||
| 	have it return ERR_PTR(-ECHILD). | ||||
| 
 | ||||
|   permission: called by the VFS to check for access rights on a POSIX-like | ||||
|   	filesystem. | ||||
|  |  | |||
|  | @ -472,6 +472,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 			Change the amount of debugging information output | ||||
| 			when initialising the APIC and IO-APIC components. | ||||
| 
 | ||||
| 	apic_extnmi=	[APIC,X86] External NMI delivery setting | ||||
| 			Format: { bsp (default) | all | none } | ||||
| 			bsp:  External NMI is delivered only to CPU 0 | ||||
| 			all:  External NMIs are broadcast to all CPUs as a | ||||
| 			      backup of CPU 0 | ||||
| 			none: External NMI is masked for all CPUs. This is | ||||
| 			      useful so that a dump capture kernel won't be | ||||
| 			      shot down by NMI | ||||
| 
 | ||||
| 	autoconf=	[IPV6] | ||||
| 			See Documentation/networking/ipv6.txt. | ||||
| 
 | ||||
|  | @ -3296,18 +3305,35 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 	rcutorture.verbose= [KNL] | ||||
| 			Enable additional printk() statements. | ||||
| 
 | ||||
| 	rcupdate.rcu_cpu_stall_suppress= [KNL] | ||||
| 			Suppress RCU CPU stall warning messages. | ||||
| 
 | ||||
| 	rcupdate.rcu_cpu_stall_timeout= [KNL] | ||||
| 			Set timeout for RCU CPU stall warning messages. | ||||
| 
 | ||||
| 	rcupdate.rcu_expedited= [KNL] | ||||
| 			Use expedited grace-period primitives, for | ||||
| 			example, synchronize_rcu_expedited() instead | ||||
| 			of synchronize_rcu().  This reduces latency, | ||||
| 			but can increase CPU utilization, degrade | ||||
| 			real-time latency, and degrade energy efficiency. | ||||
| 			No effect on CONFIG_TINY_RCU kernels. | ||||
| 
 | ||||
| 	rcupdate.rcu_cpu_stall_suppress= [KNL] | ||||
| 			Suppress RCU CPU stall warning messages. | ||||
| 	rcupdate.rcu_normal= [KNL] | ||||
| 			Use only normal grace-period primitives, | ||||
| 			for example, synchronize_rcu() instead of | ||||
| 			synchronize_rcu_expedited().  This improves | ||||
| 			real-time latency, CPU utilization, and | ||||
| 			energy efficiency, but can expose users to | ||||
| 			increased grace-period latency.  This parameter | ||||
| 			overrides rcupdate.rcu_expedited.  No effect on | ||||
| 			CONFIG_TINY_RCU kernels. | ||||
| 
 | ||||
| 	rcupdate.rcu_cpu_stall_timeout= [KNL] | ||||
| 			Set timeout for RCU CPU stall warning messages. | ||||
| 	rcupdate.rcu_normal_after_boot= [KNL] | ||||
| 			Once boot has completed (that is, after | ||||
| 			rcu_end_inkernel_boot() has been invoked), use | ||||
| 			only normal grace-period primitives.  No effect | ||||
| 			on CONFIG_TINY_RCU kernels. | ||||
| 
 | ||||
| 	rcupdate.rcu_task_stall_timeout= [KNL] | ||||
| 			Set timeout in jiffies for RCU task stall warning | ||||
|  |  | |||
|  | @ -194,7 +194,7 @@ There are some minimal guarantees that may be expected of a CPU: | |||
|  (*) On any given CPU, dependent memory accesses will be issued in order, with | ||||
|      respect to itself.  This means that for: | ||||
| 
 | ||||
| 	WRITE_ONCE(Q, P); smp_read_barrier_depends(); D = READ_ONCE(*Q); | ||||
| 	Q = READ_ONCE(P); smp_read_barrier_depends(); D = READ_ONCE(*Q); | ||||
| 
 | ||||
|      the CPU will issue the following memory operations: | ||||
| 
 | ||||
|  | @ -202,9 +202,9 @@ There are some minimal guarantees that may be expected of a CPU: | |||
| 
 | ||||
|      and always in that order.  On most systems, smp_read_barrier_depends() | ||||
|      does nothing, but it is required for DEC Alpha.  The READ_ONCE() | ||||
|      and WRITE_ONCE() are required to prevent compiler mischief.  Please | ||||
|      note that you should normally use something like rcu_dereference() | ||||
|      instead of open-coding smp_read_barrier_depends(). | ||||
|      is required to prevent compiler mischief.  Please note that you | ||||
|      should normally use something like rcu_dereference() instead of | ||||
|      open-coding smp_read_barrier_depends(). | ||||
| 
 | ||||
|  (*) Overlapping loads and stores within a particular CPU will appear to be | ||||
|      ordered within that CPU.  This means that for: | ||||
|  | @ -1673,8 +1673,8 @@ There are some more advanced barrier functions: | |||
|  (*) smp_store_mb(var, value) | ||||
| 
 | ||||
|      This assigns the value to the variable and then inserts a full memory | ||||
|      barrier after it, depending on the function.  It isn't guaranteed to | ||||
|      insert anything more than a compiler barrier in a UP compilation. | ||||
|      barrier after it.  It isn't guaranteed to insert anything more than a | ||||
|      compiler barrier in a UP compilation. | ||||
| 
 | ||||
| 
 | ||||
|  (*) smp_mb__before_atomic(); | ||||
|  |  | |||
|  | @ -551,6 +551,21 @@ the recommended setting is 60. | |||
| 
 | ||||
| ============================================================== | ||||
| 
 | ||||
| panic_on_io_nmi: | ||||
| 
 | ||||
| Controls the kernel's behavior when a CPU receives an NMI caused by | ||||
| an IO error. | ||||
| 
 | ||||
| 0: try to continue operation (default) | ||||
| 
 | ||||
| 1: panic immediately. The IO error triggered an NMI. This indicates a | ||||
|    serious system condition which could result in IO data corruption. | ||||
|    Rather than continuing, panicking might be a better choice. Some | ||||
|    servers issue this sort of NMI when the dump button is pushed, | ||||
|    and you can use this option to take a crash dump. | ||||
| 
 | ||||
| ============================================================== | ||||
| 
 | ||||
| panic_on_oops: | ||||
| 
 | ||||
| Controls the kernel's behaviour when an oops or BUG is encountered. | ||||
|  |  | |||
							
								
								
									
										37
									
								
								Documentation/trace/events-msr.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Documentation/trace/events-msr.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| 
 | ||||
| The x86 kernel supports tracing most MSR (Model Specific Register) accesses. | ||||
| To see the definition of the MSRs on Intel systems please see the SDM | ||||
| at http://www.intel.com/sdm (Volume 3) | ||||
| 
 | ||||
| Available trace points: | ||||
| 
 | ||||
| /sys/kernel/debug/tracing/events/msr/ | ||||
| 
 | ||||
| Trace MSR reads | ||||
| 
 | ||||
| read_msr | ||||
| 
 | ||||
| msr: MSR number | ||||
| val: Value written | ||||
| failed: 1 if the access failed, otherwise 0 | ||||
| 
 | ||||
| 
 | ||||
| Trace MSR writes | ||||
| 
 | ||||
| write_msr | ||||
| 
 | ||||
| msr: MSR number | ||||
| val: Value written | ||||
| failed: 1 if the access failed, otherwise 0 | ||||
| 
 | ||||
| 
 | ||||
| Trace RDPMC in kernel | ||||
| 
 | ||||
| rdpmc | ||||
| 
 | ||||
| The trace data can be post processed with the postprocess/decode_msr.py script | ||||
| 
 | ||||
| cat /sys/kernel/debug/tracing/trace | decode_msr.py /usr/src/linux/include/asm/msr-index.h | ||||
| 
 | ||||
| to add symbolic MSR names. | ||||
| 
 | ||||
							
								
								
									
										37
									
								
								Documentation/trace/postprocess/decode_msr.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Documentation/trace/postprocess/decode_msr.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| #!/usr/bin/python | ||||
| # add symbolic names to read_msr / write_msr in trace | ||||
| # decode_msr msr-index.h < trace | ||||
| import sys | ||||
| import re | ||||
| 
 | ||||
| msrs = dict() | ||||
| 
 | ||||
| with open(sys.argv[1] if len(sys.argv) > 1 else "msr-index.h", "r") as f: | ||||
| 	for j in f: | ||||
| 		m = re.match(r'#define (MSR_\w+)\s+(0x[0-9a-fA-F]+)', j) | ||||
| 		if m: | ||||
| 			msrs[int(m.group(2), 16)] = m.group(1) | ||||
| 
 | ||||
| extra_ranges = ( | ||||
| 	( "MSR_LASTBRANCH_%d_FROM_IP", 0x680, 0x69F ), | ||||
| 	( "MSR_LASTBRANCH_%d_TO_IP", 0x6C0, 0x6DF ), | ||||
| 	( "LBR_INFO_%d", 0xdc0, 0xddf ), | ||||
| ) | ||||
| 
 | ||||
| for j in sys.stdin: | ||||
| 	m = re.search(r'(read|write)_msr:\s+([0-9a-f]+)', j) | ||||
| 	if m: | ||||
| 		r = None | ||||
| 		num = int(m.group(2), 16) | ||||
| 		if num in msrs: | ||||
| 			r = msrs[num] | ||||
| 		else: | ||||
| 			for er in extra_ranges: | ||||
| 				if er[1] <= num <= er[2]: | ||||
| 					r = er[0] % (num - er[1],) | ||||
| 					break | ||||
| 		if r: | ||||
| 			j = j.replace(" " + m.group(2), " " + r + "(" + m.group(2) + ")") | ||||
| 	print j, | ||||
| 
 | ||||
| 
 | ||||
|  | @ -5622,9 +5622,7 @@ F:	Documentation/trace/intel_th.txt | |||
| F:	drivers/hwtracing/intel_th/ | ||||
| 
 | ||||
| INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) | ||||
| M:	Richard L Maliszewski <richard.l.maliszewski@intel.com> | ||||
| M:	Gang Wei <gang.wei@intel.com> | ||||
| M:	Shane Wang <shane.wang@intel.com> | ||||
| M:	Ning Sun <ning.sun@intel.com> | ||||
| L:	tboot-devel@lists.sourceforge.net | ||||
| W:	http://tboot.sourceforge.net | ||||
| T:	hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot | ||||
|  |  | |||
|  | @ -128,6 +128,5 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | |||
| #endif /* !CONFIG_SMP */ | ||||
| 
 | ||||
| #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) | ||||
| #define tas(ptr) ((void)xchg((ptr), 1)) | ||||
| 
 | ||||
| #endif /* __ARCH_BLACKFIN_CMPXCHG__ */ | ||||
|  |  | |||
|  | @ -47,8 +47,6 @@ static inline unsigned int __xchg(unsigned int x, volatile void *ptr, int size) | |||
| #define xchg(ptr, x) \ | ||||
| 	((__typeof__(*(ptr)))__xchg((unsigned int)(x), (void *) (ptr), \ | ||||
| 				    sizeof(*(ptr)))) | ||||
| #define tas(ptr)    xchg((ptr), 1) | ||||
| 
 | ||||
| 
 | ||||
| #include <asm-generic/cmpxchg-local.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -69,8 +69,6 @@ extern uint32_t __xchg_32(uint32_t i, volatile void *v); | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define tas(ptr) (xchg((ptr), 1)) | ||||
| 
 | ||||
| /*****************************************************************************/ | ||||
| /*
 | ||||
|  * compare and conditionally exchange value with memory | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ do {									\ | |||
| 	___p1;								\ | ||||
| }) | ||||
| 
 | ||||
| #define smp_store_mb(var, value)	do { WRITE_ONCE(var, value); mb(); } while (0) | ||||
| #define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0) | ||||
| 
 | ||||
| /*
 | ||||
|  * The group barrier in front of the rsm & ssm are necessary to ensure | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ | |||
| #define rmb()  __asm__ __volatile__ ("sync" : : : "memory") | ||||
| #define wmb()  __asm__ __volatile__ ("sync" : : : "memory") | ||||
| 
 | ||||
| #define smp_store_mb(var, value)	do { WRITE_ONCE(var, value); mb(); } while (0) | ||||
| #define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0) | ||||
| 
 | ||||
| #ifdef __SUBARCH_HAS_LWSYNC | ||||
| #    define SMPWMB      LWSYNC | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ | |||
| #define smp_mb__before_atomic()		smp_mb() | ||||
| #define smp_mb__after_atomic()		smp_mb() | ||||
| 
 | ||||
| #define smp_store_mb(var, value)		do { WRITE_ONCE(var, value); mb(); } while (0) | ||||
| #define smp_store_mb(var, value)	do { WRITE_ONCE(var, value); smp_mb(); } while (0) | ||||
| 
 | ||||
| #define smp_store_release(p, v)						\ | ||||
| do {									\ | ||||
|  |  | |||
|  | @ -127,8 +127,6 @@ long long _atomic64_cmpxchg(long long *v, long long o, long long n); | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define tas(ptr) xchg((ptr), 1) | ||||
| 
 | ||||
| #endif /* __ASSEMBLY__ */ | ||||
| 
 | ||||
| #endif /* _ASM_TILE_CMPXCHG_H */ | ||||
|  |  | |||
|  | @ -349,6 +349,17 @@ config X86_FEATURE_NAMES | |||
| 
 | ||||
| 	  If in doubt, say Y. | ||||
| 
 | ||||
| config X86_FAST_FEATURE_TESTS | ||||
| 	bool "Fast CPU feature tests" if EMBEDDED | ||||
| 	default y | ||||
| 	---help--- | ||||
| 	  Some fast-paths in the kernel depend on the capabilities of the CPU. | ||||
| 	  Say Y here for the kernel to patch in the appropriate code at runtime | ||||
| 	  based on the capabilities of the CPU. The infrastructure for patching | ||||
| 	  code at runtime takes up some additional space; space-constrained | ||||
| 	  embedded systems may wish to say N here to produce smaller, slightly | ||||
| 	  slower code. | ||||
| 
 | ||||
| config X86_X2APIC | ||||
| 	bool "Support x2apic" | ||||
| 	depends on X86_LOCAL_APIC && X86_64 && (IRQ_REMAP || HYPERVISOR_GUEST) | ||||
|  | @ -687,6 +698,14 @@ config PARAVIRT_SPINLOCKS | |||
| 
 | ||||
| 	  If you are unsure how to answer this question, answer Y. | ||||
| 
 | ||||
| config QUEUED_LOCK_STAT | ||||
| 	bool "Paravirt queued spinlock statistics" | ||||
| 	depends on PARAVIRT_SPINLOCKS && DEBUG_FS && QUEUED_SPINLOCKS | ||||
| 	---help--- | ||||
| 	  Enable the collection of statistical data on the slowpath | ||||
| 	  behavior of paravirtualized queued spinlocks and report | ||||
| 	  them on debugfs. | ||||
| 
 | ||||
| source "arch/x86/xen/Kconfig" | ||||
| 
 | ||||
| config KVM_GUEST | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ config X86_PTDUMP_CORE | |||
| 	def_bool n | ||||
| 
 | ||||
| config X86_PTDUMP | ||||
| 	bool "Export kernel pagetable layout to userspace via debugfs" | ||||
| 	tristate "Export kernel pagetable layout to userspace via debugfs" | ||||
| 	depends on DEBUG_KERNEL | ||||
| 	select DEBUG_FS | ||||
| 	select X86_PTDUMP_CORE | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ static struct crypto_alg alg = { | |||
| 
 | ||||
| static int __init chacha20_simd_mod_init(void) | ||||
| { | ||||
| 	if (!cpu_has_ssse3) | ||||
| 	if (!boot_cpu_has(X86_FEATURE_SSSE3)) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| #ifdef CONFIG_AS_AVX2 | ||||
|  |  | |||
|  | @ -257,7 +257,7 @@ static int __init crc32c_intel_mod_init(void) | |||
| 	if (!x86_match_cpu(crc32c_cpu_id)) | ||||
| 		return -ENODEV; | ||||
| #ifdef CONFIG_X86_64 | ||||
| 	if (cpu_has_pclmulqdq) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_PCLMULQDQ)) { | ||||
| 		alg.update = crc32c_pcl_intel_update; | ||||
| 		alg.finup = crc32c_pcl_intel_finup; | ||||
| 		alg.digest = crc32c_pcl_intel_digest; | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| #include <linux/jump_label.h> | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|  x86 function call convention, 64-bit: | ||||
|  | @ -232,3 +234,16 @@ For 32-bit we have the following conventions - kernel is built with | |||
| 
 | ||||
| #endif /* CONFIG_X86_64 */ | ||||
| 
 | ||||
| /*
 | ||||
|  * This does 'call enter_from_user_mode' unless we can avoid it based on | ||||
|  * kernel config or using the static jump infrastructure. | ||||
|  */ | ||||
| .macro CALL_enter_from_user_mode | ||||
| #ifdef CONFIG_CONTEXT_TRACKING | ||||
| #ifdef HAVE_JUMP_LABEL | ||||
| 	STATIC_JUMP_IF_FALSE .Lafter_call_\@, context_tracking_enabled, def=0 | ||||
| #endif | ||||
| 	call enter_from_user_mode | ||||
| .Lafter_call_\@: | ||||
| #endif | ||||
| .endm | ||||
|  |  | |||
|  | @ -329,7 +329,8 @@ sysenter_past_esp: | |||
| 	 * Return back to the vDSO, which will pop ecx and edx. | ||||
| 	 * Don't bother with DS and ES (they already contain __USER_DS). | ||||
| 	 */ | ||||
| 	ENABLE_INTERRUPTS_SYSEXIT | ||||
| 	sti | ||||
| 	sysexit | ||||
| 
 | ||||
| .pushsection .fixup, "ax" | ||||
| 2:	movl	$0, PT_FS(%esp) | ||||
|  | @ -552,11 +553,6 @@ ENTRY(native_iret) | |||
| 	iret | ||||
| 	_ASM_EXTABLE(native_iret, iret_exc) | ||||
| END(native_iret) | ||||
| 
 | ||||
| ENTRY(native_irq_enable_sysexit) | ||||
| 	sti | ||||
| 	sysexit | ||||
| END(native_irq_enable_sysexit) | ||||
| #endif | ||||
| 
 | ||||
| ENTRY(overflow) | ||||
|  |  | |||
|  | @ -520,9 +520,7 @@ END(irq_entries_start) | |||
| 	 */ | ||||
| 	TRACE_IRQS_OFF | ||||
| 
 | ||||
| #ifdef CONFIG_CONTEXT_TRACKING | ||||
| 	call enter_from_user_mode | ||||
| #endif | ||||
| 	CALL_enter_from_user_mode | ||||
| 
 | ||||
| 1: | ||||
| 	/* | ||||
|  | @ -1066,9 +1064,7 @@ ENTRY(error_entry) | |||
| 	 * (which can take locks). | ||||
| 	 */ | ||||
| 	TRACE_IRQS_OFF | ||||
| #ifdef CONFIG_CONTEXT_TRACKING | ||||
| 	call enter_from_user_mode | ||||
| #endif | ||||
| 	CALL_enter_from_user_mode | ||||
| 	ret | ||||
| 
 | ||||
| .Lerror_entry_done: | ||||
|  |  | |||
|  | @ -18,13 +18,6 @@ | |||
| 
 | ||||
| 	.section .entry.text, "ax" | ||||
| 
 | ||||
| #ifdef CONFIG_PARAVIRT | ||||
| ENTRY(native_usergs_sysret32) | ||||
| 	swapgs | ||||
| 	sysretl | ||||
| ENDPROC(native_usergs_sysret32) | ||||
| #endif | ||||
| 
 | ||||
| /* | ||||
|  * 32-bit SYSENTER instruction entry. | ||||
|  * | ||||
|  | @ -103,15 +96,15 @@ ENTRY(entry_SYSENTER_compat) | |||
| 	 * This needs to happen before enabling interrupts so that | ||||
| 	 * we don't get preempted with NT set. | ||||
| 	 * | ||||
| 	 * NB.: sysenter_fix_flags is a label with the code under it moved | ||||
| 	 * NB.: .Lsysenter_fix_flags is a label with the code under it moved | ||||
| 	 * out-of-line as an optimization: NT is unlikely to be set in the | ||||
| 	 * majority of the cases and instead of polluting the I$ unnecessarily, | ||||
| 	 * we're keeping that code behind a branch which will predict as | ||||
| 	 * not-taken and therefore its instructions won't be fetched. | ||||
| 	 */ | ||||
| 	testl	$X86_EFLAGS_NT, EFLAGS(%rsp) | ||||
| 	jnz	sysenter_fix_flags | ||||
| sysenter_flags_fixed: | ||||
| 	jnz	.Lsysenter_fix_flags | ||||
| .Lsysenter_flags_fixed: | ||||
| 
 | ||||
| 	/* | ||||
| 	 * User mode is traced as though IRQs are on, and SYSENTER | ||||
|  | @ -126,10 +119,10 @@ sysenter_flags_fixed: | |||
| 		    "jmp .Lsyscall_32_done", X86_FEATURE_XENPV | ||||
| 	jmp	sysret32_from_system_call | ||||
| 
 | ||||
| sysenter_fix_flags: | ||||
| .Lsysenter_fix_flags: | ||||
| 	pushq	$X86_EFLAGS_FIXED | ||||
| 	popfq | ||||
| 	jmp	sysenter_flags_fixed | ||||
| 	jmp	.Lsysenter_flags_fixed | ||||
| ENDPROC(entry_SYSENTER_compat) | ||||
| 
 | ||||
| /* | ||||
|  | @ -238,7 +231,8 @@ sysret32_from_system_call: | |||
| 	xorq	%r9, %r9 | ||||
| 	xorq	%r10, %r10 | ||||
| 	movq	RSP-ORIG_RAX(%rsp), %rsp | ||||
|         USERGS_SYSRET32 | ||||
| 	swapgs | ||||
| 	sysretl | ||||
| END(entry_SYSCALL_compat) | ||||
| 
 | ||||
| /* | ||||
|  |  | |||
|  | @ -17,8 +17,10 @@ | |||
| #include <asm/vvar.h> | ||||
| #include <asm/unistd.h> | ||||
| #include <asm/msr.h> | ||||
| #include <asm/pvclock.h> | ||||
| #include <linux/math64.h> | ||||
| #include <linux/time.h> | ||||
| #include <linux/kernel.h> | ||||
| 
 | ||||
| #define gtod (&VVAR(vsyscall_gtod_data)) | ||||
| 
 | ||||
|  | @ -36,12 +38,12 @@ static notrace cycle_t vread_hpet(void) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| #ifndef BUILD_VDSO32 | ||||
| #ifdef CONFIG_PARAVIRT_CLOCK | ||||
| extern u8 pvclock_page | ||||
| 	__attribute__((visibility("hidden"))); | ||||
| #endif | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <asm/vsyscall.h> | ||||
| #include <asm/fixmap.h> | ||||
| #include <asm/pvclock.h> | ||||
| #ifndef BUILD_VDSO32 | ||||
| 
 | ||||
| notrace static long vdso_fallback_gettime(long clock, struct timespec *ts) | ||||
| { | ||||
|  | @ -60,75 +62,6 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_PARAVIRT_CLOCK | ||||
| 
 | ||||
| static notrace const struct pvclock_vsyscall_time_info *get_pvti(int cpu) | ||||
| { | ||||
| 	const struct pvclock_vsyscall_time_info *pvti_base; | ||||
| 	int idx = cpu / (PAGE_SIZE/PVTI_SIZE); | ||||
| 	int offset = cpu % (PAGE_SIZE/PVTI_SIZE); | ||||
| 
 | ||||
| 	BUG_ON(PVCLOCK_FIXMAP_BEGIN + idx > PVCLOCK_FIXMAP_END); | ||||
| 
 | ||||
| 	pvti_base = (struct pvclock_vsyscall_time_info *) | ||||
| 		    __fix_to_virt(PVCLOCK_FIXMAP_BEGIN+idx); | ||||
| 
 | ||||
| 	return &pvti_base[offset]; | ||||
| } | ||||
| 
 | ||||
| static notrace cycle_t vread_pvclock(int *mode) | ||||
| { | ||||
| 	const struct pvclock_vsyscall_time_info *pvti; | ||||
| 	cycle_t ret; | ||||
| 	u64 last; | ||||
| 	u32 version; | ||||
| 	u8 flags; | ||||
| 	unsigned cpu, cpu1; | ||||
| 
 | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Note: hypervisor must guarantee that: | ||||
| 	 * 1. cpu ID number maps 1:1 to per-CPU pvclock time info. | ||||
| 	 * 2. that per-CPU pvclock time info is updated if the | ||||
| 	 *    underlying CPU changes. | ||||
| 	 * 3. that version is increased whenever underlying CPU | ||||
| 	 *    changes. | ||||
| 	 * | ||||
| 	 */ | ||||
| 	do { | ||||
| 		cpu = __getcpu() & VGETCPU_CPU_MASK; | ||||
| 		/* TODO: We can put vcpu id into higher bits of pvti.version.
 | ||||
| 		 * This will save a couple of cycles by getting rid of | ||||
| 		 * __getcpu() calls (Gleb). | ||||
| 		 */ | ||||
| 
 | ||||
| 		pvti = get_pvti(cpu); | ||||
| 
 | ||||
| 		version = __pvclock_read_cycles(&pvti->pvti, &ret, &flags); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Test we're still on the cpu as well as the version. | ||||
| 		 * We could have been migrated just after the first | ||||
| 		 * vgetcpu but before fetching the version, so we | ||||
| 		 * wouldn't notice a version change. | ||||
| 		 */ | ||||
| 		cpu1 = __getcpu() & VGETCPU_CPU_MASK; | ||||
| 	} while (unlikely(cpu != cpu1 || | ||||
| 			  (pvti->pvti.version & 1) || | ||||
| 			  pvti->pvti.version != version)); | ||||
| 
 | ||||
| 	if (unlikely(!(flags & PVCLOCK_TSC_STABLE_BIT))) | ||||
| 		*mode = VCLOCK_NONE; | ||||
| 
 | ||||
| 	/* refer to tsc.c read_tsc() comment for rationale */ | ||||
| 	last = gtod->cycle_last; | ||||
| 
 | ||||
| 	if (likely(ret >= last)) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return last; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|  | @ -162,15 +95,77 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_PARAVIRT_CLOCK | ||||
| static notrace const struct pvclock_vsyscall_time_info *get_pvti0(void) | ||||
| { | ||||
| 	return (const struct pvclock_vsyscall_time_info *)&pvclock_page; | ||||
| } | ||||
| 
 | ||||
| static notrace cycle_t vread_pvclock(int *mode) | ||||
| { | ||||
| 	const struct pvclock_vcpu_time_info *pvti = &get_pvti0()->pvti; | ||||
| 	cycle_t ret; | ||||
| 	u64 tsc, pvti_tsc; | ||||
| 	u64 last, delta, pvti_system_time; | ||||
| 	u32 version, pvti_tsc_to_system_mul, pvti_tsc_shift; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Note: The kernel and hypervisor must guarantee that cpu ID | ||||
| 	 * number maps 1:1 to per-CPU pvclock time info. | ||||
| 	 * | ||||
| 	 * Because the hypervisor is entirely unaware of guest userspace | ||||
| 	 * preemption, it cannot guarantee that per-CPU pvclock time | ||||
| 	 * info is updated if the underlying CPU changes or that that | ||||
| 	 * version is increased whenever underlying CPU changes. | ||||
| 	 * | ||||
| 	 * On KVM, we are guaranteed that pvti updates for any vCPU are | ||||
| 	 * atomic as seen by *all* vCPUs.  This is an even stronger | ||||
| 	 * guarantee than we get with a normal seqlock. | ||||
| 	 * | ||||
| 	 * On Xen, we don't appear to have that guarantee, but Xen still | ||||
| 	 * supplies a valid seqlock using the version field. | ||||
| 
 | ||||
| 	 * We only do pvclock vdso timing at all if | ||||
| 	 * PVCLOCK_TSC_STABLE_BIT is set, and we interpret that bit to | ||||
| 	 * mean that all vCPUs have matching pvti and that the TSC is | ||||
| 	 * synced, so we can just look at vCPU 0's pvti. | ||||
| 	 */ | ||||
| 
 | ||||
| 	if (unlikely(!(pvti->flags & PVCLOCK_TSC_STABLE_BIT))) { | ||||
| 		*mode = VCLOCK_NONE; | ||||
| 		return 0; | ||||
| } | ||||
| #endif | ||||
| 	} | ||||
| 
 | ||||
| 	do { | ||||
| 		version = pvti->version; | ||||
| 
 | ||||
| 		smp_rmb(); | ||||
| 
 | ||||
| 		tsc = rdtsc_ordered(); | ||||
| 		pvti_tsc_to_system_mul = pvti->tsc_to_system_mul; | ||||
| 		pvti_tsc_shift = pvti->tsc_shift; | ||||
| 		pvti_system_time = pvti->system_time; | ||||
| 		pvti_tsc = pvti->tsc_timestamp; | ||||
| 
 | ||||
| 		/* Make sure that the version double-check is last. */ | ||||
| 		smp_rmb(); | ||||
| 	} while (unlikely((version & 1) || version != pvti->version)); | ||||
| 
 | ||||
| 	delta = tsc - pvti_tsc; | ||||
| 	ret = pvti_system_time + | ||||
| 		pvclock_scale_delta(delta, pvti_tsc_to_system_mul, | ||||
| 				    pvti_tsc_shift); | ||||
| 
 | ||||
| 	/* refer to vread_tsc() comment for rationale */ | ||||
| 	last = gtod->cycle_last; | ||||
| 
 | ||||
| 	if (likely(ret >= last)) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return last; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| notrace static cycle_t vread_tsc(void) | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ SECTIONS | |||
| 	 * segment. | ||||
| 	 */ | ||||
| 
 | ||||
| 	vvar_start = . - 2 * PAGE_SIZE;
 | ||||
| 	vvar_start = . - 3 * PAGE_SIZE;
 | ||||
| 	vvar_page = vvar_start;
 | ||||
| 
 | ||||
| 	/* Place all vvars at the offsets in asm/vvar.h. */ | ||||
|  | @ -36,6 +36,7 @@ SECTIONS | |||
| #undef EMIT_VVAR | ||||
| 
 | ||||
| 	hpet_page = vvar_start + PAGE_SIZE;
 | ||||
| 	pvclock_page = vvar_start + 2 * PAGE_SIZE;
 | ||||
| 
 | ||||
| 	. = SIZEOF_HEADERS;
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ enum { | |||
| 	sym_vvar_start, | ||||
| 	sym_vvar_page, | ||||
| 	sym_hpet_page, | ||||
| 	sym_pvclock_page, | ||||
| 	sym_VDSO_FAKE_SECTION_TABLE_START, | ||||
| 	sym_VDSO_FAKE_SECTION_TABLE_END, | ||||
| }; | ||||
|  | @ -80,6 +81,7 @@ enum { | |||
| const int special_pages[] = { | ||||
| 	sym_vvar_page, | ||||
| 	sym_hpet_page, | ||||
| 	sym_pvclock_page, | ||||
| }; | ||||
| 
 | ||||
| struct vdso_sym { | ||||
|  | @ -91,6 +93,7 @@ struct vdso_sym required_syms[] = { | |||
| 	[sym_vvar_start] = {"vvar_start", true}, | ||||
| 	[sym_vvar_page] = {"vvar_page", true}, | ||||
| 	[sym_hpet_page] = {"hpet_page", true}, | ||||
| 	[sym_pvclock_page] = {"pvclock_page", true}, | ||||
| 	[sym_VDSO_FAKE_SECTION_TABLE_START] = { | ||||
| 		"VDSO_FAKE_SECTION_TABLE_START", false | ||||
| 	}, | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ | |||
| #include <linux/random.h> | ||||
| #include <linux/elf.h> | ||||
| #include <linux/cpu.h> | ||||
| #include <asm/pvclock.h> | ||||
| #include <asm/vgtod.h> | ||||
| #include <asm/proto.h> | ||||
| #include <asm/vdso.h> | ||||
|  | @ -100,6 +101,7 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) | |||
| 		.name = "[vvar]", | ||||
| 		.pages = no_pages, | ||||
| 	}; | ||||
| 	struct pvclock_vsyscall_time_info *pvti; | ||||
| 
 | ||||
| 	if (calculate_addr) { | ||||
| 		addr = vdso_addr(current->mm->start_stack, | ||||
|  | @ -169,6 +171,18 @@ static int map_vdso(const struct vdso_image *image, bool calculate_addr) | |||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	pvti = pvclock_pvti_cpu0_va(); | ||||
| 	if (pvti && image->sym_pvclock_page) { | ||||
| 		ret = remap_pfn_range(vma, | ||||
| 				      text_start + image->sym_pvclock_page, | ||||
| 				      __pa(pvti) >> PAGE_SHIFT, | ||||
| 				      PAGE_SIZE, | ||||
| 				      PAGE_READONLY); | ||||
| 
 | ||||
| 		if (ret) | ||||
| 			goto up_fail; | ||||
| 	} | ||||
| 
 | ||||
| up_fail: | ||||
| 	if (ret) | ||||
| 		current->mm->context.vdso = NULL; | ||||
|  |  | |||
|  | @ -23,6 +23,11 @@ | |||
| #define APIC_VERBOSE 1 | ||||
| #define APIC_DEBUG   2 | ||||
| 
 | ||||
| /* Macros for apic_extnmi which controls external NMI masking */ | ||||
| #define APIC_EXTNMI_BSP		0 /* Default */ | ||||
| #define APIC_EXTNMI_ALL		1 | ||||
| #define APIC_EXTNMI_NONE	2 | ||||
| 
 | ||||
| /*
 | ||||
|  * Define the default level of output to be very little | ||||
|  * This can be turned up by using apic=verbose for more | ||||
|  | @ -303,6 +308,7 @@ struct apic { | |||
| 				      unsigned int *apicid); | ||||
| 
 | ||||
| 	/* ipi */ | ||||
| 	void (*send_IPI)(int cpu, int vector); | ||||
| 	void (*send_IPI_mask)(const struct cpumask *mask, int vector); | ||||
| 	void (*send_IPI_mask_allbutself)(const struct cpumask *mask, | ||||
| 					 int vector); | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
| 
 | ||||
| #include <linux/compiler.h> | ||||
| #include <linux/types.h> | ||||
| #include <asm/processor.h> | ||||
| #include <asm/alternative.h> | ||||
| #include <asm/cmpxchg.h> | ||||
| #include <asm/rmwcc.h> | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
| 
 | ||||
| #include <linux/compiler.h> | ||||
| #include <linux/types.h> | ||||
| #include <asm/processor.h> | ||||
| //#include <asm/cmpxchg.h>
 | ||||
| 
 | ||||
| /* An 64bit atomic type */ | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ | |||
| #include <asm/types.h> | ||||
| 
 | ||||
| struct iommu_table { | ||||
| 	struct cal_chipset_ops *chip_ops; /* chipset specific funcs */ | ||||
| 	const struct cal_chipset_ops *chip_ops; /* chipset specific funcs */ | ||||
| 	unsigned long  it_base;      /* mapped address of tce table */ | ||||
| 	unsigned long  it_hint;      /* Hint for next alloc */ | ||||
| 	unsigned long *it_map;       /* A simple allocation bitmap for now */ | ||||
|  |  | |||
|  | @ -109,6 +109,6 @@ static inline u64 __cmpxchg64_local(volatile u64 *ptr, u64 old, u64 new) | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define system_has_cmpxchg_double() cpu_has_cx8 | ||||
| #define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX8) | ||||
| 
 | ||||
| #endif /* _ASM_X86_CMPXCHG_32_H */ | ||||
|  |  | |||
|  | @ -18,6 +18,6 @@ static inline void set_64bit(volatile u64 *ptr, u64 val) | |||
| 	cmpxchg_local((ptr), (o), (n));					\ | ||||
| }) | ||||
| 
 | ||||
| #define system_has_cmpxchg_double() cpu_has_cx16 | ||||
| #define system_has_cmpxchg_double() boot_cpu_has(X86_FEATURE_CX16) | ||||
| 
 | ||||
| #endif /* _ASM_X86_CMPXCHG_64_H */ | ||||
|  |  | |||
|  | @ -36,4 +36,7 @@ extern int _debug_hotplug_cpu(int cpu, int action); | |||
| 
 | ||||
| int mwait_usable(const struct cpuinfo_x86 *); | ||||
| 
 | ||||
| unsigned int x86_family(unsigned int sig); | ||||
| unsigned int x86_model(unsigned int sig); | ||||
| unsigned int x86_stepping(unsigned int sig); | ||||
| #endif /* _ASM_X86_CPU_H */ | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| #include <asm/disabled-features.h> | ||||
| #endif | ||||
| 
 | ||||
| #define NCAPINTS	14	/* N 32-bit words worth of info */ | ||||
| #define NCAPINTS	16	/* N 32-bit words worth of info */ | ||||
| #define NBUGINTS	1	/* N 32-bit bug flags */ | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -181,22 +181,17 @@ | |||
| 
 | ||||
| /*
 | ||||
|  * Auxiliary flags: Linux defined - For features scattered in various | ||||
|  * CPUID levels like 0x6, 0xA etc, word 7 | ||||
|  * CPUID levels like 0x6, 0xA etc, word 7. | ||||
|  * | ||||
|  * Reuse free bits when adding new feature flags! | ||||
|  */ | ||||
| #define X86_FEATURE_IDA		( 7*32+ 0) /* Intel Dynamic Acceleration */ | ||||
| #define X86_FEATURE_ARAT	( 7*32+ 1) /* Always Running APIC Timer */ | ||||
| 
 | ||||
| #define X86_FEATURE_CPB		( 7*32+ 2) /* AMD Core Performance Boost */ | ||||
| #define X86_FEATURE_EPB		( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */ | ||||
| #define X86_FEATURE_PLN		( 7*32+ 5) /* Intel Power Limit Notification */ | ||||
| #define X86_FEATURE_PTS		( 7*32+ 6) /* Intel Package Thermal Status */ | ||||
| #define X86_FEATURE_DTHERM	( 7*32+ 7) /* Digital Thermal Sensor */ | ||||
| 
 | ||||
| #define X86_FEATURE_HW_PSTATE	( 7*32+ 8) /* AMD HW-PState */ | ||||
| #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ | ||||
| #define X86_FEATURE_HWP		( 7*32+ 10) /* "hwp" Intel HWP */ | ||||
| #define X86_FEATURE_HWP_NOTIFY	( 7*32+ 11) /* Intel HWP_NOTIFY */ | ||||
| #define X86_FEATURE_HWP_ACT_WINDOW ( 7*32+ 12) /* Intel HWP_ACT_WINDOW */ | ||||
| #define X86_FEATURE_HWP_EPP	( 7*32+13) /* Intel HWP_EPP */ | ||||
| #define X86_FEATURE_HWP_PKG_REQ ( 7*32+14) /* Intel HWP_PKG_REQ */ | ||||
| 
 | ||||
| #define X86_FEATURE_INTEL_PT	( 7*32+15) /* Intel Processor Trace */ | ||||
| 
 | ||||
| /* Virtualization flags: Linux defined, word 8 */ | ||||
|  | @ -205,16 +200,7 @@ | |||
| #define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */ | ||||
| #define X86_FEATURE_EPT         ( 8*32+ 3) /* Intel Extended Page Table */ | ||||
| #define X86_FEATURE_VPID        ( 8*32+ 4) /* Intel Virtual Processor ID */ | ||||
| #define X86_FEATURE_NPT		( 8*32+ 5) /* AMD Nested Page Table support */ | ||||
| #define X86_FEATURE_LBRV	( 8*32+ 6) /* AMD LBR Virtualization support */ | ||||
| #define X86_FEATURE_SVML	( 8*32+ 7) /* "svm_lock" AMD SVM locking MSR */ | ||||
| #define X86_FEATURE_NRIPS	( 8*32+ 8) /* "nrip_save" AMD SVM next_rip save */ | ||||
| #define X86_FEATURE_TSCRATEMSR  ( 8*32+ 9) /* "tsc_scale" AMD TSC scaling support */ | ||||
| #define X86_FEATURE_VMCBCLEAN   ( 8*32+10) /* "vmcb_clean" AMD VMCB clean bits support */ | ||||
| #define X86_FEATURE_FLUSHBYASID ( 8*32+11) /* AMD flush-by-ASID support */ | ||||
| #define X86_FEATURE_DECODEASSISTS ( 8*32+12) /* AMD Decode Assists support */ | ||||
| #define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */ | ||||
| #define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */ | ||||
| 
 | ||||
| #define X86_FEATURE_VMMCALL     ( 8*32+15) /* Prefer vmmcall to vmcall */ | ||||
| #define X86_FEATURE_XENPV       ( 8*32+16) /* "" Xen paravirtual guest */ | ||||
| 
 | ||||
|  | @ -259,6 +245,30 @@ | |||
| /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ | ||||
| #define X86_FEATURE_CLZERO	(13*32+0) /* CLZERO instruction */ | ||||
| 
 | ||||
| /* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */ | ||||
| #define X86_FEATURE_DTHERM	(14*32+ 0) /* Digital Thermal Sensor */ | ||||
| #define X86_FEATURE_IDA		(14*32+ 1) /* Intel Dynamic Acceleration */ | ||||
| #define X86_FEATURE_ARAT	(14*32+ 2) /* Always Running APIC Timer */ | ||||
| #define X86_FEATURE_PLN		(14*32+ 4) /* Intel Power Limit Notification */ | ||||
| #define X86_FEATURE_PTS		(14*32+ 6) /* Intel Package Thermal Status */ | ||||
| #define X86_FEATURE_HWP		(14*32+ 7) /* Intel Hardware P-states */ | ||||
| #define X86_FEATURE_HWP_NOTIFY	(14*32+ 8) /* HWP Notification */ | ||||
| #define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */ | ||||
| #define X86_FEATURE_HWP_EPP	(14*32+10) /* HWP Energy Perf. Preference */ | ||||
| #define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */ | ||||
| 
 | ||||
| /* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */ | ||||
| #define X86_FEATURE_NPT		(15*32+ 0) /* Nested Page Table support */ | ||||
| #define X86_FEATURE_LBRV	(15*32+ 1) /* LBR Virtualization support */ | ||||
| #define X86_FEATURE_SVML	(15*32+ 2) /* "svm_lock" SVM locking MSR */ | ||||
| #define X86_FEATURE_NRIPS	(15*32+ 3) /* "nrip_save" SVM next_rip save */ | ||||
| #define X86_FEATURE_TSCRATEMSR  (15*32+ 4) /* "tsc_scale" TSC scaling support */ | ||||
| #define X86_FEATURE_VMCBCLEAN   (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */ | ||||
| #define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */ | ||||
| #define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */ | ||||
| #define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */ | ||||
| #define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */ | ||||
| 
 | ||||
| /*
 | ||||
|  * BUG word(s) | ||||
|  */ | ||||
|  | @ -279,6 +289,26 @@ | |||
| #include <asm/asm.h> | ||||
| #include <linux/bitops.h> | ||||
| 
 | ||||
| enum cpuid_leafs | ||||
| { | ||||
| 	CPUID_1_EDX		= 0, | ||||
| 	CPUID_8000_0001_EDX, | ||||
| 	CPUID_8086_0001_EDX, | ||||
| 	CPUID_LNX_1, | ||||
| 	CPUID_1_ECX, | ||||
| 	CPUID_C000_0001_EDX, | ||||
| 	CPUID_8000_0001_ECX, | ||||
| 	CPUID_LNX_2, | ||||
| 	CPUID_LNX_3, | ||||
| 	CPUID_7_0_EBX, | ||||
| 	CPUID_D_1_EAX, | ||||
| 	CPUID_F_0_EDX, | ||||
| 	CPUID_F_1_EDX, | ||||
| 	CPUID_8000_0008_EBX, | ||||
| 	CPUID_6_EAX, | ||||
| 	CPUID_8000_000A_EDX, | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_X86_FEATURE_NAMES | ||||
| extern const char * const x86_cap_flags[NCAPINTS*32]; | ||||
| extern const char * const x86_power_flags[32]; | ||||
|  | @ -356,60 +386,31 @@ extern const char * const x86_bug_flags[NBUGINTS*32]; | |||
| } while (0) | ||||
| 
 | ||||
| #define cpu_has_fpu		boot_cpu_has(X86_FEATURE_FPU) | ||||
| #define cpu_has_de		boot_cpu_has(X86_FEATURE_DE) | ||||
| #define cpu_has_pse		boot_cpu_has(X86_FEATURE_PSE) | ||||
| #define cpu_has_tsc		boot_cpu_has(X86_FEATURE_TSC) | ||||
| #define cpu_has_pge		boot_cpu_has(X86_FEATURE_PGE) | ||||
| #define cpu_has_apic		boot_cpu_has(X86_FEATURE_APIC) | ||||
| #define cpu_has_sep		boot_cpu_has(X86_FEATURE_SEP) | ||||
| #define cpu_has_mtrr		boot_cpu_has(X86_FEATURE_MTRR) | ||||
| #define cpu_has_mmx		boot_cpu_has(X86_FEATURE_MMX) | ||||
| #define cpu_has_fxsr		boot_cpu_has(X86_FEATURE_FXSR) | ||||
| #define cpu_has_xmm		boot_cpu_has(X86_FEATURE_XMM) | ||||
| #define cpu_has_xmm2		boot_cpu_has(X86_FEATURE_XMM2) | ||||
| #define cpu_has_xmm3		boot_cpu_has(X86_FEATURE_XMM3) | ||||
| #define cpu_has_ssse3		boot_cpu_has(X86_FEATURE_SSSE3) | ||||
| #define cpu_has_aes		boot_cpu_has(X86_FEATURE_AES) | ||||
| #define cpu_has_avx		boot_cpu_has(X86_FEATURE_AVX) | ||||
| #define cpu_has_avx2		boot_cpu_has(X86_FEATURE_AVX2) | ||||
| #define cpu_has_ht		boot_cpu_has(X86_FEATURE_HT) | ||||
| #define cpu_has_nx		boot_cpu_has(X86_FEATURE_NX) | ||||
| #define cpu_has_xstore		boot_cpu_has(X86_FEATURE_XSTORE) | ||||
| #define cpu_has_xstore_enabled	boot_cpu_has(X86_FEATURE_XSTORE_EN) | ||||
| #define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT) | ||||
| #define cpu_has_xcrypt_enabled	boot_cpu_has(X86_FEATURE_XCRYPT_EN) | ||||
| #define cpu_has_ace2		boot_cpu_has(X86_FEATURE_ACE2) | ||||
| #define cpu_has_ace2_enabled	boot_cpu_has(X86_FEATURE_ACE2_EN) | ||||
| #define cpu_has_phe		boot_cpu_has(X86_FEATURE_PHE) | ||||
| #define cpu_has_phe_enabled	boot_cpu_has(X86_FEATURE_PHE_EN) | ||||
| #define cpu_has_pmm		boot_cpu_has(X86_FEATURE_PMM) | ||||
| #define cpu_has_pmm_enabled	boot_cpu_has(X86_FEATURE_PMM_EN) | ||||
| #define cpu_has_ds		boot_cpu_has(X86_FEATURE_DS) | ||||
| #define cpu_has_pebs		boot_cpu_has(X86_FEATURE_PEBS) | ||||
| #define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLUSH) | ||||
| #define cpu_has_bts		boot_cpu_has(X86_FEATURE_BTS) | ||||
| #define cpu_has_gbpages		boot_cpu_has(X86_FEATURE_GBPAGES) | ||||
| #define cpu_has_arch_perfmon	boot_cpu_has(X86_FEATURE_ARCH_PERFMON) | ||||
| #define cpu_has_pat		boot_cpu_has(X86_FEATURE_PAT) | ||||
| #define cpu_has_xmm4_1		boot_cpu_has(X86_FEATURE_XMM4_1) | ||||
| #define cpu_has_xmm4_2		boot_cpu_has(X86_FEATURE_XMM4_2) | ||||
| #define cpu_has_x2apic		boot_cpu_has(X86_FEATURE_X2APIC) | ||||
| #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE) | ||||
| #define cpu_has_xsaveopt	boot_cpu_has(X86_FEATURE_XSAVEOPT) | ||||
| #define cpu_has_xsaves		boot_cpu_has(X86_FEATURE_XSAVES) | ||||
| #define cpu_has_osxsave		boot_cpu_has(X86_FEATURE_OSXSAVE) | ||||
| #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR) | ||||
| #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ) | ||||
| #define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE) | ||||
| #define cpu_has_perfctr_nb	boot_cpu_has(X86_FEATURE_PERFCTR_NB) | ||||
| #define cpu_has_perfctr_l2	boot_cpu_has(X86_FEATURE_PERFCTR_L2) | ||||
| #define cpu_has_cx8		boot_cpu_has(X86_FEATURE_CX8) | ||||
| #define cpu_has_cx16		boot_cpu_has(X86_FEATURE_CX16) | ||||
| #define cpu_has_eager_fpu	boot_cpu_has(X86_FEATURE_EAGER_FPU) | ||||
| #define cpu_has_topoext		boot_cpu_has(X86_FEATURE_TOPOEXT) | ||||
| #define cpu_has_bpext		boot_cpu_has(X86_FEATURE_BPEXT) | ||||
| /*
 | ||||
|  * Do not add any more of those clumsy macros - use static_cpu_has_safe() for | ||||
|  * fast paths and boot_cpu_has() otherwise! | ||||
|  */ | ||||
| 
 | ||||
| #if __GNUC__ >= 4 | ||||
| #if __GNUC__ >= 4 && defined(CONFIG_X86_FAST_FEATURE_TESTS) | ||||
| extern void warn_pre_alternatives(void); | ||||
| extern bool __static_cpu_has_safe(u16 bit); | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ | |||
| #include <asm/acpi.h> | ||||
| #include <asm/apicdef.h> | ||||
| #include <asm/page.h> | ||||
| #include <asm/pvclock.h> | ||||
| #ifdef CONFIG_X86_32 | ||||
| #include <linux/threads.h> | ||||
| #include <asm/kmap_types.h> | ||||
|  | @ -72,10 +71,6 @@ enum fixed_addresses { | |||
| #ifdef CONFIG_X86_VSYSCALL_EMULATION | ||||
| 	VSYSCALL_PAGE = (FIXADDR_TOP - VSYSCALL_ADDR) >> PAGE_SHIFT, | ||||
| #endif | ||||
| #ifdef CONFIG_PARAVIRT_CLOCK | ||||
| 	PVCLOCK_FIXMAP_BEGIN, | ||||
| 	PVCLOCK_FIXMAP_END = PVCLOCK_FIXMAP_BEGIN+PVCLOCK_VSYSCALL_NR_PAGES-1, | ||||
| #endif | ||||
| #endif | ||||
| 	FIX_DBGP_BASE, | ||||
| 	FIX_EARLYCON_MEM_BASE, | ||||
|  |  | |||
|  | @ -224,18 +224,67 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) | |||
| #define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f" | ||||
| #define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f" | ||||
| 
 | ||||
| /* xstate instruction fault handler: */ | ||||
| #define xstate_fault(__err)		\ | ||||
| 					\ | ||||
| 	".section .fixup,\"ax\"\n"	\ | ||||
| 					\ | ||||
| 	"3:  movl $-2,%[_err]\n"	\ | ||||
| 	"    jmp  2b\n"			\ | ||||
| 					\ | ||||
| 	".previous\n"			\ | ||||
| 					\ | ||||
| #define XSTATE_OP(op, st, lmask, hmask, err)				\ | ||||
| 	asm volatile("1:" op "\n\t"					\ | ||||
| 		     "xor %[err], %[err]\n"				\ | ||||
| 		     "2:\n\t"						\ | ||||
| 		     ".pushsection .fixup,\"ax\"\n\t"			\ | ||||
| 		     "3: movl $-2,%[err]\n\t"				\ | ||||
| 		     "jmp 2b\n\t"					\ | ||||
| 		     ".popsection\n\t"					\ | ||||
| 		     _ASM_EXTABLE(1b, 3b)				\ | ||||
| 	: [_err] "=r" (__err) | ||||
| 		     : [err] "=r" (err)					\ | ||||
| 		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\ | ||||
| 		     : "memory") | ||||
| 
 | ||||
| /*
 | ||||
|  * If XSAVES is enabled, it replaces XSAVEOPT because it supports a compact | ||||
|  * format and supervisor states in addition to modified optimization in | ||||
|  * XSAVEOPT. | ||||
|  * | ||||
|  * Otherwise, if XSAVEOPT is enabled, XSAVEOPT replaces XSAVE because XSAVEOPT | ||||
|  * supports modified optimization which is not supported by XSAVE. | ||||
|  * | ||||
|  * We use XSAVE as a fallback. | ||||
|  * | ||||
|  * The 661 label is defined in the ALTERNATIVE* macros as the address of the | ||||
|  * original instruction which gets replaced. We need to use it here as the | ||||
|  * address of the instruction where we might get an exception at. | ||||
|  */ | ||||
| #define XSTATE_XSAVE(st, lmask, hmask, err)				\ | ||||
| 	asm volatile(ALTERNATIVE_2(XSAVE,				\ | ||||
| 				   XSAVEOPT, X86_FEATURE_XSAVEOPT,	\ | ||||
| 				   XSAVES,   X86_FEATURE_XSAVES)	\ | ||||
| 		     "\n"						\ | ||||
| 		     "xor %[err], %[err]\n"				\ | ||||
| 		     "3:\n"						\ | ||||
| 		     ".pushsection .fixup,\"ax\"\n"			\ | ||||
| 		     "4: movl $-2, %[err]\n"				\ | ||||
| 		     "jmp 3b\n"						\ | ||||
| 		     ".popsection\n"					\ | ||||
| 		     _ASM_EXTABLE(661b, 4b)				\ | ||||
| 		     : [err] "=r" (err)					\ | ||||
| 		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\ | ||||
| 		     : "memory") | ||||
| 
 | ||||
| /*
 | ||||
|  * Use XRSTORS to restore context if it is enabled. XRSTORS supports compact | ||||
|  * XSAVE area format. | ||||
|  */ | ||||
| #define XSTATE_XRESTORE(st, lmask, hmask, err)				\ | ||||
| 	asm volatile(ALTERNATIVE(XRSTOR,				\ | ||||
| 				 XRSTORS, X86_FEATURE_XSAVES)		\ | ||||
| 		     "\n"						\ | ||||
| 		     "xor %[err], %[err]\n"				\ | ||||
| 		     "3:\n"						\ | ||||
| 		     ".pushsection .fixup,\"ax\"\n"			\ | ||||
| 		     "4: movl $-2, %[err]\n"				\ | ||||
| 		     "jmp 3b\n"						\ | ||||
| 		     ".popsection\n"					\ | ||||
| 		     _ASM_EXTABLE(661b, 4b)				\ | ||||
| 		     : [err] "=r" (err)					\ | ||||
| 		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\ | ||||
| 		     : "memory") | ||||
| 
 | ||||
| /*
 | ||||
|  * This function is called only during boot time when x86 caps are not set | ||||
|  | @ -246,22 +295,14 @@ static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) | |||
| 	u64 mask = -1; | ||||
| 	u32 lmask = mask; | ||||
| 	u32 hmask = mask >> 32; | ||||
| 	int err = 0; | ||||
| 	int err; | ||||
| 
 | ||||
| 	WARN_ON(system_state != SYSTEM_BOOTING); | ||||
| 
 | ||||
| 	if (boot_cpu_has(X86_FEATURE_XSAVES)) | ||||
| 		asm volatile("1:"XSAVES"\n\t" | ||||
| 			"2:\n\t" | ||||
| 			     xstate_fault(err) | ||||
| 			: "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) | ||||
| 			: "memory"); | ||||
| 	if (static_cpu_has_safe(X86_FEATURE_XSAVES)) | ||||
| 		XSTATE_OP(XSAVES, xstate, lmask, hmask, err); | ||||
| 	else | ||||
| 		asm volatile("1:"XSAVE"\n\t" | ||||
| 			"2:\n\t" | ||||
| 			     xstate_fault(err) | ||||
| 			: "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) | ||||
| 			: "memory"); | ||||
| 		XSTATE_OP(XSAVE, xstate, lmask, hmask, err); | ||||
| 
 | ||||
| 	/* We should never fault when copying to a kernel buffer: */ | ||||
| 	WARN_ON_FPU(err); | ||||
|  | @ -276,22 +317,14 @@ static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate) | |||
| 	u64 mask = -1; | ||||
| 	u32 lmask = mask; | ||||
| 	u32 hmask = mask >> 32; | ||||
| 	int err = 0; | ||||
| 	int err; | ||||
| 
 | ||||
| 	WARN_ON(system_state != SYSTEM_BOOTING); | ||||
| 
 | ||||
| 	if (boot_cpu_has(X86_FEATURE_XSAVES)) | ||||
| 		asm volatile("1:"XRSTORS"\n\t" | ||||
| 			"2:\n\t" | ||||
| 			     xstate_fault(err) | ||||
| 			: "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) | ||||
| 			: "memory"); | ||||
| 	if (static_cpu_has_safe(X86_FEATURE_XSAVES)) | ||||
| 		XSTATE_OP(XRSTORS, xstate, lmask, hmask, err); | ||||
| 	else | ||||
| 		asm volatile("1:"XRSTOR"\n\t" | ||||
| 			"2:\n\t" | ||||
| 			     xstate_fault(err) | ||||
| 			: "D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask), "0" (err) | ||||
| 			: "memory"); | ||||
| 		XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); | ||||
| 
 | ||||
| 	/* We should never fault when copying from a kernel buffer: */ | ||||
| 	WARN_ON_FPU(err); | ||||
|  | @ -305,33 +338,11 @@ static inline void copy_xregs_to_kernel(struct xregs_state *xstate) | |||
| 	u64 mask = -1; | ||||
| 	u32 lmask = mask; | ||||
| 	u32 hmask = mask >> 32; | ||||
| 	int err = 0; | ||||
| 	int err; | ||||
| 
 | ||||
| 	WARN_ON(!alternatives_patched); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If xsaves is enabled, xsaves replaces xsaveopt because | ||||
| 	 * it supports compact format and supervisor states in addition to | ||||
| 	 * modified optimization in xsaveopt. | ||||
| 	 * | ||||
| 	 * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave | ||||
| 	 * because xsaveopt supports modified optimization which is not | ||||
| 	 * supported by xsave. | ||||
| 	 * | ||||
| 	 * If none of xsaves and xsaveopt is enabled, use xsave. | ||||
| 	 */ | ||||
| 	alternative_input_2( | ||||
| 		"1:"XSAVE, | ||||
| 		XSAVEOPT, | ||||
| 		X86_FEATURE_XSAVEOPT, | ||||
| 		XSAVES, | ||||
| 		X86_FEATURE_XSAVES, | ||||
| 		[xstate] "D" (xstate), "a" (lmask), "d" (hmask) : | ||||
| 		"memory"); | ||||
| 	asm volatile("2:\n\t" | ||||
| 		     xstate_fault(err) | ||||
| 		     : "0" (err) | ||||
| 		     : "memory"); | ||||
| 	XSTATE_XSAVE(xstate, lmask, hmask, err); | ||||
| 
 | ||||
| 	/* We should never fault when copying to a kernel buffer: */ | ||||
| 	WARN_ON_FPU(err); | ||||
|  | @ -344,23 +355,9 @@ static inline void copy_kernel_to_xregs(struct xregs_state *xstate, u64 mask) | |||
| { | ||||
| 	u32 lmask = mask; | ||||
| 	u32 hmask = mask >> 32; | ||||
| 	int err = 0; | ||||
| 	int err; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Use xrstors to restore context if it is enabled. xrstors supports | ||||
| 	 * compacted format of xsave area which is not supported by xrstor. | ||||
| 	 */ | ||||
| 	alternative_input( | ||||
| 		"1: " XRSTOR, | ||||
| 		XRSTORS, | ||||
| 		X86_FEATURE_XSAVES, | ||||
| 		"D" (xstate), "m" (*xstate), "a" (lmask), "d" (hmask) | ||||
| 		: "memory"); | ||||
| 
 | ||||
| 	asm volatile("2:\n" | ||||
| 		     xstate_fault(err) | ||||
| 		     : "0" (err) | ||||
| 		     : "memory"); | ||||
| 	XSTATE_XRESTORE(xstate, lmask, hmask, err); | ||||
| 
 | ||||
| 	/* We should never fault when copying from a kernel buffer: */ | ||||
| 	WARN_ON_FPU(err); | ||||
|  | @ -388,12 +385,10 @@ static inline int copy_xregs_to_user(struct xregs_state __user *buf) | |||
| 	if (unlikely(err)) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	__asm__ __volatile__(ASM_STAC "\n" | ||||
| 			     "1:"XSAVE"\n" | ||||
| 			     "2: " ASM_CLAC "\n" | ||||
| 			     xstate_fault(err) | ||||
| 			     : "D" (buf), "a" (-1), "d" (-1), "0" (err) | ||||
| 			     : "memory"); | ||||
| 	stac(); | ||||
| 	XSTATE_OP(XSAVE, buf, -1, -1, err); | ||||
| 	clac(); | ||||
| 
 | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
|  | @ -405,14 +400,12 @@ static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask) | |||
| 	struct xregs_state *xstate = ((__force struct xregs_state *)buf); | ||||
| 	u32 lmask = mask; | ||||
| 	u32 hmask = mask >> 32; | ||||
| 	int err = 0; | ||||
| 	int err; | ||||
| 
 | ||||
| 	stac(); | ||||
| 	XSTATE_OP(XRSTOR, xstate, lmask, hmask, err); | ||||
| 	clac(); | ||||
| 
 | ||||
| 	__asm__ __volatile__(ASM_STAC "\n" | ||||
| 			     "1:"XRSTOR"\n" | ||||
| 			     "2: " ASM_CLAC "\n" | ||||
| 			     xstate_fault(err) | ||||
| 			     : "D" (xstate), "a" (lmask), "d" (hmask), "0" (err) | ||||
| 			     : "memory");	/* memory required? */ | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								arch/x86/include/asm/intel_pt.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								arch/x86/include/asm/intel_pt.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| #ifndef _ASM_X86_INTEL_PT_H | ||||
| #define _ASM_X86_INTEL_PT_H | ||||
| 
 | ||||
| #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) | ||||
| void cpu_emergency_stop_pt(void); | ||||
| #else | ||||
| static inline void cpu_emergency_stop_pt(void) {} | ||||
| #endif | ||||
| 
 | ||||
| #endif /* _ASM_X86_INTEL_PT_H */ | ||||
|  | @ -119,6 +119,8 @@ static inline void | |||
| 	native_apic_mem_write(APIC_ICR, cfg); | ||||
| } | ||||
| 
 | ||||
| extern void default_send_IPI_single(int cpu, int vector); | ||||
| extern void default_send_IPI_single_phys(int cpu, int vector); | ||||
| extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, | ||||
| 						 int vector); | ||||
| extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, | ||||
|  |  | |||
|  | @ -1,12 +1,18 @@ | |||
| #ifndef _ASM_X86_JUMP_LABEL_H | ||||
| #define _ASM_X86_JUMP_LABEL_H | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| 
 | ||||
| #include <linux/stringify.h> | ||||
| #include <linux/types.h> | ||||
| #include <asm/nops.h> | ||||
| #include <asm/asm.h> | ||||
| #ifndef HAVE_JUMP_LABEL | ||||
| /*
 | ||||
|  * For better or for worse, if jump labels (the gcc extension) are missing, | ||||
|  * then the entire static branch patching infrastructure is compiled out. | ||||
|  * If that happens, the code in here will malfunction.  Raise a compiler | ||||
|  * error instead. | ||||
|  * | ||||
|  * In theory, jump labels and the static branch patching infrastructure | ||||
|  * could be decoupled to fix this. | ||||
|  */ | ||||
| #error asm/jump_label.h included on a non-jump-label kernel | ||||
| #endif | ||||
| 
 | ||||
| #define JUMP_LABEL_NOP_SIZE 5 | ||||
| 
 | ||||
|  | @ -16,6 +22,14 @@ | |||
| # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC | ||||
| #endif | ||||
| 
 | ||||
| #include <asm/asm.h> | ||||
| #include <asm/nops.h> | ||||
| 
 | ||||
| #ifndef __ASSEMBLY__ | ||||
| 
 | ||||
| #include <linux/stringify.h> | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| static __always_inline bool arch_static_branch(struct static_key *key, bool branch) | ||||
| { | ||||
| 	asm_volatile_goto("1:" | ||||
|  | @ -59,5 +73,40 @@ struct jump_entry { | |||
| 	jump_label_t key; | ||||
| }; | ||||
| 
 | ||||
| #else	/* __ASSEMBLY__ */ | ||||
| 
 | ||||
| .macro STATIC_JUMP_IF_TRUE target, key, def | ||||
| .Lstatic_jump_\@: | ||||
| 	.if \def | ||||
| 	/* Equivalent to "jmp.d32 \target" */ | ||||
| 	.byte		0xe9 | ||||
| 	.long		\target - .Lstatic_jump_after_\@ | ||||
| .Lstatic_jump_after_\@: | ||||
| 	.else | ||||
| 	.byte		STATIC_KEY_INIT_NOP | ||||
| 	.endif | ||||
| 	.pushsection __jump_table, "aw" | ||||
| 	_ASM_ALIGN | ||||
| 	_ASM_PTR	.Lstatic_jump_\@, \target, \key | ||||
| 	.popsection | ||||
| .endm | ||||
| 
 | ||||
| .macro STATIC_JUMP_IF_FALSE target, key, def | ||||
| .Lstatic_jump_\@: | ||||
| 	.if \def | ||||
| 	.byte		STATIC_KEY_INIT_NOP | ||||
| 	.else | ||||
| 	/* Equivalent to "jmp.d32 \target" */ | ||||
| 	.byte		0xe9 | ||||
| 	.long		\target - .Lstatic_jump_after_\@ | ||||
| .Lstatic_jump_after_\@: | ||||
| 	.endif | ||||
| 	.pushsection __jump_table, "aw" | ||||
| 	_ASM_ALIGN | ||||
| 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1 | ||||
| 	.popsection | ||||
| .endm | ||||
| 
 | ||||
| #endif	/* __ASSEMBLY__ */ | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| #ifndef _ASM_X86_MICROCODE_H | ||||
| #define _ASM_X86_MICROCODE_H | ||||
| 
 | ||||
| #include <asm/cpu.h> | ||||
| #include <linux/earlycpio.h> | ||||
| 
 | ||||
| #define native_rdmsr(msr, val1, val2)			\ | ||||
|  | @ -95,14 +96,14 @@ static inline void __exit exit_amd_microcode(void) {} | |||
| 
 | ||||
| /*
 | ||||
|  * In early loading microcode phase on BSP, boot_cpu_data is not set up yet. | ||||
|  * x86_vendor() gets vendor id for BSP. | ||||
|  * x86_cpuid_vendor() gets vendor id for BSP. | ||||
|  * | ||||
|  * In 32 bit AP case, accessing boot_cpu_data needs linear address. To simplify | ||||
|  * coding, we still use x86_vendor() to get vendor id for AP. | ||||
|  * coding, we still use x86_cpuid_vendor() to get vendor id for AP. | ||||
|  * | ||||
|  * x86_vendor() gets vendor information directly from CPUID. | ||||
|  * x86_cpuid_vendor() gets vendor information directly from CPUID. | ||||
|  */ | ||||
| static inline int x86_vendor(void) | ||||
| static inline int x86_cpuid_vendor(void) | ||||
| { | ||||
| 	u32 eax = 0x00000000; | ||||
| 	u32 ebx, ecx = 0, edx; | ||||
|  | @ -118,40 +119,14 @@ static inline int x86_vendor(void) | |||
| 	return X86_VENDOR_UNKNOWN; | ||||
| } | ||||
| 
 | ||||
| static inline unsigned int __x86_family(unsigned int sig) | ||||
| { | ||||
| 	unsigned int x86; | ||||
| 
 | ||||
| 	x86 = (sig >> 8) & 0xf; | ||||
| 
 | ||||
| 	if (x86 == 0xf) | ||||
| 		x86 += (sig >> 20) & 0xff; | ||||
| 
 | ||||
| 	return x86; | ||||
| } | ||||
| 
 | ||||
| static inline unsigned int x86_family(void) | ||||
| static inline unsigned int x86_cpuid_family(void) | ||||
| { | ||||
| 	u32 eax = 0x00000001; | ||||
| 	u32 ebx, ecx = 0, edx; | ||||
| 
 | ||||
| 	native_cpuid(&eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 	return __x86_family(eax); | ||||
| } | ||||
| 
 | ||||
| static inline unsigned int x86_model(unsigned int sig) | ||||
| { | ||||
| 	unsigned int x86, model; | ||||
| 
 | ||||
| 	x86 = __x86_family(sig); | ||||
| 
 | ||||
| 	model = (sig >> 4) & 0xf; | ||||
| 
 | ||||
| 	if (x86 == 0x6 || x86 == 0xf) | ||||
| 		model += ((sig >> 16) & 0xf) << 4; | ||||
| 
 | ||||
| 	return model; | ||||
| 	return x86_family(eax); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_MICROCODE | ||||
|  |  | |||
|  | @ -1,7 +1,13 @@ | |||
| #ifndef _ASM_X86_MSI_H | ||||
| #define _ASM_X86_MSI_H | ||||
| #include <asm/hw_irq.h> | ||||
| #include <asm/irqdomain.h> | ||||
| 
 | ||||
| typedef struct irq_alloc_info msi_alloc_info_t; | ||||
| 
 | ||||
| int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, | ||||
| 		    msi_alloc_info_t *arg); | ||||
| 
 | ||||
| void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc); | ||||
| 
 | ||||
| #endif /* _ASM_X86_MSI_H */ | ||||
|  |  | |||
|  | @ -321,6 +321,7 @@ | |||
| #define MSR_F15H_PERF_CTR		0xc0010201 | ||||
| #define MSR_F15H_NB_PERF_CTL		0xc0010240 | ||||
| #define MSR_F15H_NB_PERF_CTR		0xc0010241 | ||||
| #define MSR_F15H_IC_CFG			0xc0011021 | ||||
| 
 | ||||
| /* Fam 10h MSRs */ | ||||
| #define MSR_FAM10H_MMIO_CONF_BASE	0xc0010058 | ||||
|  |  | |||
							
								
								
									
										57
									
								
								arch/x86/include/asm/msr-trace.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								arch/x86/include/asm/msr-trace.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | |||
| #undef TRACE_SYSTEM | ||||
| #define TRACE_SYSTEM msr | ||||
| 
 | ||||
| #undef TRACE_INCLUDE_FILE | ||||
| #define TRACE_INCLUDE_FILE msr-trace | ||||
| 
 | ||||
| #undef TRACE_INCLUDE_PATH | ||||
| #define TRACE_INCLUDE_PATH asm/ | ||||
| 
 | ||||
| #if !defined(_TRACE_MSR_H) || defined(TRACE_HEADER_MULTI_READ) | ||||
| #define _TRACE_MSR_H | ||||
| 
 | ||||
| #include <linux/tracepoint.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Tracing for x86 model specific registers. Directly maps to the | ||||
|  * RDMSR/WRMSR instructions. | ||||
|  */ | ||||
| 
 | ||||
| DECLARE_EVENT_CLASS(msr_trace_class, | ||||
| 	    TP_PROTO(unsigned msr, u64 val, int failed), | ||||
| 	    TP_ARGS(msr, val, failed), | ||||
| 	    TP_STRUCT__entry( | ||||
| 		    __field(	unsigned,	msr ) | ||||
| 		    __field(    u64,		val ) | ||||
| 		    __field(    int,		failed ) | ||||
| 	    ), | ||||
| 	    TP_fast_assign( | ||||
| 		    __entry->msr = msr; | ||||
| 		    __entry->val = val; | ||||
| 		    __entry->failed = failed; | ||||
| 	    ), | ||||
| 	    TP_printk("%x, value %llx%s", | ||||
| 		      __entry->msr, | ||||
| 		      __entry->val, | ||||
| 		      __entry->failed ? " #GP" : "") | ||||
| ); | ||||
| 
 | ||||
| DEFINE_EVENT(msr_trace_class, read_msr, | ||||
| 	     TP_PROTO(unsigned msr, u64 val, int failed), | ||||
| 	     TP_ARGS(msr, val, failed) | ||||
| ); | ||||
| 
 | ||||
| DEFINE_EVENT(msr_trace_class, write_msr, | ||||
| 	     TP_PROTO(unsigned msr, u64 val, int failed), | ||||
| 	     TP_ARGS(msr, val, failed) | ||||
| ); | ||||
| 
 | ||||
| DEFINE_EVENT(msr_trace_class, rdpmc, | ||||
| 	     TP_PROTO(unsigned msr, u64 val, int failed), | ||||
| 	     TP_ARGS(msr, val, failed) | ||||
| ); | ||||
| 
 | ||||
| #endif /* _TRACE_MSR_H */ | ||||
| 
 | ||||
| /* This part must be outside protection */ | ||||
| #include <trace/define_trace.h> | ||||
|  | @ -32,6 +32,16 @@ struct msr_regs_info { | |||
| 	int err; | ||||
| }; | ||||
| 
 | ||||
| struct saved_msr { | ||||
| 	bool valid; | ||||
| 	struct msr_info info; | ||||
| }; | ||||
| 
 | ||||
| struct saved_msrs { | ||||
| 	unsigned int num; | ||||
| 	struct saved_msr *array; | ||||
| }; | ||||
| 
 | ||||
| static inline unsigned long long native_read_tscp(unsigned int *aux) | ||||
| { | ||||
| 	unsigned long low, high; | ||||
|  | @ -57,11 +67,34 @@ static inline unsigned long long native_read_tscp(unsigned int *aux) | |||
| #define EAX_EDX_RET(val, low, high)	"=A" (val) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_TRACEPOINTS | ||||
| /*
 | ||||
|  * Be very careful with includes. This header is prone to include loops. | ||||
|  */ | ||||
| #include <asm/atomic.h> | ||||
| #include <linux/tracepoint-defs.h> | ||||
| 
 | ||||
| extern struct tracepoint __tracepoint_read_msr; | ||||
| extern struct tracepoint __tracepoint_write_msr; | ||||
| extern struct tracepoint __tracepoint_rdpmc; | ||||
| #define msr_tracepoint_active(t) static_key_false(&(t).key) | ||||
| extern void do_trace_write_msr(unsigned msr, u64 val, int failed); | ||||
| extern void do_trace_read_msr(unsigned msr, u64 val, int failed); | ||||
| extern void do_trace_rdpmc(unsigned msr, u64 val, int failed); | ||||
| #else | ||||
| #define msr_tracepoint_active(t) false | ||||
| static inline void do_trace_write_msr(unsigned msr, u64 val, int failed) {} | ||||
| static inline void do_trace_read_msr(unsigned msr, u64 val, int failed) {} | ||||
| static inline void do_trace_rdpmc(unsigned msr, u64 val, int failed) {} | ||||
| #endif | ||||
| 
 | ||||
| static inline unsigned long long native_read_msr(unsigned int msr) | ||||
| { | ||||
| 	DECLARE_ARGS(val, low, high); | ||||
| 
 | ||||
| 	asm volatile("rdmsr" : EAX_EDX_RET(val, low, high) : "c" (msr)); | ||||
| 	if (msr_tracepoint_active(__tracepoint_read_msr)) | ||||
| 		do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), 0); | ||||
| 	return EAX_EDX_VAL(val, low, high); | ||||
| } | ||||
| 
 | ||||
|  | @ -78,6 +111,8 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr, | |||
| 		     _ASM_EXTABLE(2b, 3b) | ||||
| 		     : [err] "=r" (*err), EAX_EDX_RET(val, low, high) | ||||
| 		     : "c" (msr), [fault] "i" (-EIO)); | ||||
| 	if (msr_tracepoint_active(__tracepoint_read_msr)) | ||||
| 		do_trace_read_msr(msr, EAX_EDX_VAL(val, low, high), *err); | ||||
| 	return EAX_EDX_VAL(val, low, high); | ||||
| } | ||||
| 
 | ||||
|  | @ -85,6 +120,8 @@ static inline void native_write_msr(unsigned int msr, | |||
| 				    unsigned low, unsigned high) | ||||
| { | ||||
| 	asm volatile("wrmsr" : : "c" (msr), "a"(low), "d" (high) : "memory"); | ||||
| 	if (msr_tracepoint_active(__tracepoint_read_msr)) | ||||
| 		do_trace_write_msr(msr, ((u64)high << 32 | low), 0); | ||||
| } | ||||
| 
 | ||||
| /* Can be uninlined because referenced by paravirt */ | ||||
|  | @ -102,6 +139,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr, | |||
| 		     : "c" (msr), "0" (low), "d" (high), | ||||
| 		       [fault] "i" (-EIO) | ||||
| 		     : "memory"); | ||||
| 	if (msr_tracepoint_active(__tracepoint_read_msr)) | ||||
| 		do_trace_write_msr(msr, ((u64)high << 32 | low), err); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
|  | @ -160,6 +199,8 @@ static inline unsigned long long native_read_pmc(int counter) | |||
| 	DECLARE_ARGS(val, low, high); | ||||
| 
 | ||||
| 	asm volatile("rdpmc" : EAX_EDX_RET(val, low, high) : "c" (counter)); | ||||
| 	if (msr_tracepoint_active(__tracepoint_rdpmc)) | ||||
| 		do_trace_rdpmc(counter, EAX_EDX_VAL(val, low, high), 0); | ||||
| 	return EAX_EDX_VAL(val, low, high); | ||||
| } | ||||
| 
 | ||||
|  | @ -190,7 +231,7 @@ static inline void wrmsr(unsigned msr, unsigned low, unsigned high) | |||
| 
 | ||||
| static inline void wrmsrl(unsigned msr, u64 val) | ||||
| { | ||||
| 	native_write_msr(msr, (u32)val, (u32)(val >> 32)); | ||||
| 	native_write_msr(msr, (u32)(val & 0xffffffffULL), (u32)(val >> 32)); | ||||
| } | ||||
| 
 | ||||
| /* wrmsr with exception handling */ | ||||
|  |  | |||
|  | @ -291,15 +291,6 @@ static inline void slow_down_io(void) | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_SMP | ||||
| static inline void startup_ipi_hook(int phys_apicid, unsigned long start_eip, | ||||
| 				    unsigned long start_esp) | ||||
| { | ||||
| 	PVOP_VCALL3(pv_apic_ops.startup_ipi_hook, | ||||
| 		    phys_apicid, start_eip, start_esp); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static inline void paravirt_activate_mm(struct mm_struct *prev, | ||||
| 					struct mm_struct *next) | ||||
| { | ||||
|  | @ -381,23 +372,6 @@ static inline void pte_update(struct mm_struct *mm, unsigned long addr, | |||
| { | ||||
| 	PVOP_VCALL3(pv_mmu_ops.pte_update, mm, addr, ptep); | ||||
| } | ||||
| static inline void pmd_update(struct mm_struct *mm, unsigned long addr, | ||||
| 			      pmd_t *pmdp) | ||||
| { | ||||
| 	PVOP_VCALL3(pv_mmu_ops.pmd_update, mm, addr, pmdp); | ||||
| } | ||||
| 
 | ||||
| static inline void pte_update_defer(struct mm_struct *mm, unsigned long addr, | ||||
| 				    pte_t *ptep) | ||||
| { | ||||
| 	PVOP_VCALL3(pv_mmu_ops.pte_update_defer, mm, addr, ptep); | ||||
| } | ||||
| 
 | ||||
| static inline void pmd_update_defer(struct mm_struct *mm, unsigned long addr, | ||||
| 				    pmd_t *pmdp) | ||||
| { | ||||
| 	PVOP_VCALL3(pv_mmu_ops.pmd_update_defer, mm, addr, pmdp); | ||||
| } | ||||
| 
 | ||||
| static inline pte_t __pte(pteval_t val) | ||||
| { | ||||
|  | @ -928,23 +902,11 @@ extern void default_banner(void); | |||
| 		  call PARA_INDIRECT(pv_irq_ops+PV_IRQ_irq_enable);	\ | ||||
| 		  PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) | ||||
| 
 | ||||
| #define USERGS_SYSRET32							\ | ||||
| 	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret32),	\ | ||||
| 		  CLBR_NONE,						\ | ||||
| 		  jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_usergs_sysret32)) | ||||
| 
 | ||||
| #ifdef CONFIG_X86_32 | ||||
| #define GET_CR0_INTO_EAX				\ | ||||
| 	push %ecx; push %edx;				\ | ||||
| 	call PARA_INDIRECT(pv_cpu_ops+PV_CPU_read_cr0);	\ | ||||
| 	pop %edx; pop %ecx | ||||
| 
 | ||||
| #define ENABLE_INTERRUPTS_SYSEXIT					\ | ||||
| 	PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_irq_enable_sysexit),	\ | ||||
| 		  CLBR_NONE,						\ | ||||
| 		  jmp PARA_INDIRECT(pv_cpu_ops+PV_CPU_irq_enable_sysexit)) | ||||
| 
 | ||||
| 
 | ||||
| #else	/* !CONFIG_X86_32 */ | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -162,15 +162,6 @@ struct pv_cpu_ops { | |||
| 
 | ||||
| 	u64 (*read_pmc)(int counter); | ||||
| 
 | ||||
| #ifdef CONFIG_X86_32 | ||||
| 	/*
 | ||||
| 	 * Atomically enable interrupts and return to userspace.  This | ||||
| 	 * is only used in 32-bit kernels.  64-bit kernels use | ||||
| 	 * usergs_sysret32 instead. | ||||
| 	 */ | ||||
| 	void (*irq_enable_sysexit)(void); | ||||
| #endif | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Switch to usermode gs and return to 64-bit usermode using | ||||
| 	 * sysret.  Only used in 64-bit kernels to return to 64-bit | ||||
|  | @ -179,14 +170,6 @@ struct pv_cpu_ops { | |||
| 	 */ | ||||
| 	void (*usergs_sysret64)(void); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Switch to usermode gs and return to 32-bit usermode using | ||||
| 	 * sysret.  Used to return to 32-on-64 compat processes. | ||||
| 	 * Other usermode register state, including %esp, must already | ||||
| 	 * be restored. | ||||
| 	 */ | ||||
| 	void (*usergs_sysret32)(void); | ||||
| 
 | ||||
| 	/* Normal iret.  Jump to this with the standard iret stack
 | ||||
| 	   frame set up. */ | ||||
| 	void (*iret)(void); | ||||
|  | @ -220,14 +203,6 @@ struct pv_irq_ops { | |||
| #endif | ||||
| }; | ||||
| 
 | ||||
| struct pv_apic_ops { | ||||
| #ifdef CONFIG_X86_LOCAL_APIC | ||||
| 	void (*startup_ipi_hook)(int phys_apicid, | ||||
| 				 unsigned long start_eip, | ||||
| 				 unsigned long start_esp); | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| struct pv_mmu_ops { | ||||
| 	unsigned long (*read_cr2)(void); | ||||
| 	void (*write_cr2)(unsigned long); | ||||
|  | @ -279,12 +254,6 @@ struct pv_mmu_ops { | |||
| 			   pmd_t *pmdp, pmd_t pmdval); | ||||
| 	void (*pte_update)(struct mm_struct *mm, unsigned long addr, | ||||
| 			   pte_t *ptep); | ||||
| 	void (*pte_update_defer)(struct mm_struct *mm, | ||||
| 				 unsigned long addr, pte_t *ptep); | ||||
| 	void (*pmd_update)(struct mm_struct *mm, unsigned long addr, | ||||
| 			   pmd_t *pmdp); | ||||
| 	void (*pmd_update_defer)(struct mm_struct *mm, | ||||
| 				 unsigned long addr, pmd_t *pmdp); | ||||
| 
 | ||||
| 	pte_t (*ptep_modify_prot_start)(struct mm_struct *mm, unsigned long addr, | ||||
| 					pte_t *ptep); | ||||
|  | @ -359,7 +328,6 @@ struct paravirt_patch_template { | |||
| 	struct pv_time_ops pv_time_ops; | ||||
| 	struct pv_cpu_ops pv_cpu_ops; | ||||
| 	struct pv_irq_ops pv_irq_ops; | ||||
| 	struct pv_apic_ops pv_apic_ops; | ||||
| 	struct pv_mmu_ops pv_mmu_ops; | ||||
| 	struct pv_lock_ops pv_lock_ops; | ||||
| }; | ||||
|  | @ -369,7 +337,6 @@ extern struct pv_init_ops pv_init_ops; | |||
| extern struct pv_time_ops pv_time_ops; | ||||
| extern struct pv_cpu_ops pv_cpu_ops; | ||||
| extern struct pv_irq_ops pv_irq_ops; | ||||
| extern struct pv_apic_ops pv_apic_ops; | ||||
| extern struct pv_mmu_ops pv_mmu_ops; | ||||
| extern struct pv_lock_ops pv_lock_ops; | ||||
| 
 | ||||
|  | @ -407,10 +374,8 @@ extern struct pv_lock_ops pv_lock_ops; | |||
| 	__visible extern const char start_##ops##_##name[], end_##ops##_##name[];	\ | ||||
| 	asm(NATIVE_LABEL("start_", ops, name) code NATIVE_LABEL("end_", ops, name)) | ||||
| 
 | ||||
| unsigned paravirt_patch_nop(void); | ||||
| unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len); | ||||
| unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len); | ||||
| unsigned paravirt_patch_ignore(unsigned len); | ||||
| unsigned paravirt_patch_call(void *insnbuf, | ||||
| 			     const void *target, u16 tgt_clobbers, | ||||
| 			     unsigned long addr, u16 site_clobbers, | ||||
|  |  | |||
|  | @ -69,9 +69,6 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); | |||
| #define pmd_clear(pmd)			native_pmd_clear(pmd) | ||||
| 
 | ||||
| #define pte_update(mm, addr, ptep)              do { } while (0) | ||||
| #define pte_update_defer(mm, addr, ptep)        do { } while (0) | ||||
| #define pmd_update(mm, addr, ptep)              do { } while (0) | ||||
| #define pmd_update_defer(mm, addr, ptep)        do { } while (0) | ||||
| 
 | ||||
| #define pgd_val(x)	native_pgd_val(x) | ||||
| #define __pgd(x)	native_make_pgd(x) | ||||
|  | @ -731,14 +728,9 @@ static inline void native_set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
|  * updates should either be sets, clears, or set_pte_atomic for P->P | ||||
|  * transitions, which means this hook should only be called for user PTEs. | ||||
|  * This hook implies a P->P protection or access change has taken place, which | ||||
|  * requires a subsequent TLB flush.  The notification can optionally be delayed | ||||
|  * until the TLB flush event by using the pte_update_defer form of the | ||||
|  * interface, but care must be taken to assure that the flush happens while | ||||
|  * still holding the same page table lock so that the shadow and primary pages | ||||
|  * do not become out of sync on SMP. | ||||
|  * requires a subsequent TLB flush. | ||||
|  */ | ||||
| #define pte_update(mm, addr, ptep)		do { } while (0) | ||||
| #define pte_update_defer(mm, addr, ptep)	do { } while (0) | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -830,9 +822,7 @@ static inline int pmd_write(pmd_t pmd) | |||
| static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, unsigned long addr, | ||||
| 				       pmd_t *pmdp) | ||||
| { | ||||
| 	pmd_t pmd = native_pmdp_get_and_clear(pmdp); | ||||
| 	pmd_update(mm, addr, pmdp); | ||||
| 	return pmd; | ||||
| 	return native_pmdp_get_and_clear(pmdp); | ||||
| } | ||||
| 
 | ||||
| #define __HAVE_ARCH_PMDP_SET_WRPROTECT | ||||
|  | @ -840,7 +830,6 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, | |||
| 				      unsigned long addr, pmd_t *pmdp) | ||||
| { | ||||
| 	clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp); | ||||
| 	pmd_update(mm, addr, pmdp); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -4,6 +4,15 @@ | |||
| #include <linux/clocksource.h> | ||||
| #include <asm/pvclock-abi.h> | ||||
| 
 | ||||
| #ifdef CONFIG_KVM_GUEST | ||||
| extern struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void); | ||||
| #else | ||||
| static inline struct pvclock_vsyscall_time_info *pvclock_pvti_cpu0_va(void) | ||||
| { | ||||
| 	return NULL; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /* some helper functions for xen and kvm pv clock sources */ | ||||
| cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src); | ||||
| u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src); | ||||
|  | @ -91,10 +100,5 @@ struct pvclock_vsyscall_time_info { | |||
| } __attribute__((__aligned__(SMP_CACHE_BYTES))); | ||||
| 
 | ||||
| #define PVTI_SIZE sizeof(struct pvclock_vsyscall_time_info) | ||||
| #define PVCLOCK_VSYSCALL_NR_PAGES (((NR_CPUS-1)/(PAGE_SIZE/PVTI_SIZE))+1) | ||||
| 
 | ||||
| int __init pvclock_init_vsyscall(struct pvclock_vsyscall_time_info *i, | ||||
| 				 int size); | ||||
| struct pvclock_vcpu_time_info *pvclock_get_vsyscall_time_info(int cpu); | ||||
| 
 | ||||
| #endif /* _ASM_X86_PVCLOCK_H */ | ||||
|  |  | |||
|  | @ -1,6 +1,65 @@ | |||
| #ifndef __ASM_QSPINLOCK_PARAVIRT_H | ||||
| #define __ASM_QSPINLOCK_PARAVIRT_H | ||||
| 
 | ||||
| /*
 | ||||
|  * For x86-64, PV_CALLEE_SAVE_REGS_THUNK() saves and restores 8 64-bit | ||||
|  * registers. For i386, however, only 1 32-bit register needs to be saved | ||||
|  * and restored. So an optimized version of __pv_queued_spin_unlock() is | ||||
|  * hand-coded for 64-bit, but it isn't worthwhile to do it for 32-bit. | ||||
|  */ | ||||
| #ifdef CONFIG_64BIT | ||||
| 
 | ||||
| PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath); | ||||
| #define __pv_queued_spin_unlock	__pv_queued_spin_unlock | ||||
| #define PV_UNLOCK		"__raw_callee_save___pv_queued_spin_unlock" | ||||
| #define PV_UNLOCK_SLOWPATH	"__raw_callee_save___pv_queued_spin_unlock_slowpath" | ||||
| 
 | ||||
| /*
 | ||||
|  * Optimized assembly version of __raw_callee_save___pv_queued_spin_unlock | ||||
|  * which combines the registers saving trunk and the body of the following | ||||
|  * C code: | ||||
|  * | ||||
|  * void __pv_queued_spin_unlock(struct qspinlock *lock) | ||||
|  * { | ||||
|  *	struct __qspinlock *l = (void *)lock; | ||||
|  *	u8 lockval = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0); | ||||
|  * | ||||
|  *	if (likely(lockval == _Q_LOCKED_VAL)) | ||||
|  *		return; | ||||
|  *	pv_queued_spin_unlock_slowpath(lock, lockval); | ||||
|  * } | ||||
|  * | ||||
|  * For x86-64, | ||||
|  *   rdi = lock              (first argument) | ||||
|  *   rsi = lockval           (second argument) | ||||
|  *   rdx = internal variable (set to 0) | ||||
|  */ | ||||
| asm    (".pushsection .text;" | ||||
| 	".globl " PV_UNLOCK ";" | ||||
| 	".align 4,0x90;" | ||||
| 	PV_UNLOCK ": " | ||||
| 	"push  %rdx;" | ||||
| 	"mov   $0x1,%eax;" | ||||
| 	"xor   %edx,%edx;" | ||||
| 	"lock cmpxchg %dl,(%rdi);" | ||||
| 	"cmp   $0x1,%al;" | ||||
| 	"jne   .slowpath;" | ||||
| 	"pop   %rdx;" | ||||
| 	"ret;" | ||||
| 	".slowpath: " | ||||
| 	"push   %rsi;" | ||||
| 	"movzbl %al,%esi;" | ||||
| 	"call " PV_UNLOCK_SLOWPATH ";" | ||||
| 	"pop    %rsi;" | ||||
| 	"pop    %rdx;" | ||||
| 	"ret;" | ||||
| 	".size " PV_UNLOCK ", .-" PV_UNLOCK ";" | ||||
| 	".popsection"); | ||||
| 
 | ||||
| #else /* CONFIG_64BIT */ | ||||
| 
 | ||||
| extern void __pv_queued_spin_unlock(struct qspinlock *lock); | ||||
| PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock); | ||||
| 
 | ||||
| #endif /* CONFIG_64BIT */ | ||||
| #endif | ||||
|  |  | |||
|  | @ -25,5 +25,6 @@ void __noreturn machine_real_restart(unsigned int type); | |||
| 
 | ||||
| typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); | ||||
| void nmi_shootdown_cpus(nmi_shootdown_cb callback); | ||||
| void run_crash_ipi_callback(struct pt_regs *regs); | ||||
| 
 | ||||
| #endif /* _ASM_X86_REBOOT_H */ | ||||
|  |  | |||
|  | @ -21,15 +21,6 @@ | |||
| extern int smp_num_siblings; | ||||
| extern unsigned int num_processors; | ||||
| 
 | ||||
| static inline bool cpu_has_ht_siblings(void) | ||||
| { | ||||
| 	bool has_siblings = false; | ||||
| #ifdef CONFIG_SMP | ||||
| 	has_siblings = cpu_has_ht && smp_num_siblings > 1; | ||||
| #endif | ||||
| 	return has_siblings; | ||||
| } | ||||
| 
 | ||||
| DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); | ||||
| DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); | ||||
| /* cpus sharing the last level cache: */ | ||||
|  | @ -74,9 +65,6 @@ struct smp_ops { | |||
| extern void set_cpu_sibling_map(int cpu); | ||||
| 
 | ||||
| #ifdef CONFIG_SMP | ||||
| #ifndef CONFIG_PARAVIRT | ||||
| #define startup_ipi_hook(phys_apicid, start_eip, start_esp) do { } while (0) | ||||
| #endif | ||||
| extern struct smp_ops smp_ops; | ||||
| 
 | ||||
| static inline void smp_send_stop(void) | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ struct saved_context { | |||
| 	unsigned long cr0, cr2, cr3, cr4; | ||||
| 	u64 misc_enable; | ||||
| 	bool misc_enable_saved; | ||||
| 	struct saved_msrs saved_msrs; | ||||
| 	struct desc_ptr gdt_desc; | ||||
| 	struct desc_ptr idt; | ||||
| 	u16 ldt; | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ struct saved_context { | |||
| 	unsigned long cr0, cr2, cr3, cr4, cr8; | ||||
| 	u64 misc_enable; | ||||
| 	bool misc_enable_saved; | ||||
| 	struct saved_msrs saved_msrs; | ||||
| 	unsigned long efer; | ||||
| 	u16 gdt_pad; /* Unused */ | ||||
| 	struct desc_ptr gdt_desc; | ||||
|  |  | |||
|  | @ -745,5 +745,14 @@ copy_to_user(void __user *to, const void *from, unsigned long n) | |||
| #undef __copy_from_user_overflow | ||||
| #undef __copy_to_user_overflow | ||||
| 
 | ||||
| /*
 | ||||
|  * We rely on the nested NMI work to allow atomic faults from the NMI path; the | ||||
|  * nested NMI paths are careful to preserve CR2. | ||||
|  * | ||||
|  * Caller must use pagefault_enable/disable, or run in interrupt context, | ||||
|  * and also do a uaccess_ok() check | ||||
|  */ | ||||
| #define __copy_from_user_nmi __copy_from_user_inatomic | ||||
| 
 | ||||
| #endif /* _ASM_X86_UACCESS_H */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ struct vdso_image { | |||
| 
 | ||||
| 	long sym_vvar_page; | ||||
| 	long sym_hpet_page; | ||||
| 	long sym_pvclock_page; | ||||
| 	long sym_VDSO32_NOTE_MASK; | ||||
| 	long sym___kernel_sigreturn; | ||||
| 	long sym___kernel_rt_sigreturn; | ||||
|  |  | |||
|  | @ -82,13 +82,11 @@ struct x86_init_paging { | |||
|  * struct x86_init_timers - platform specific timer setup | ||||
|  * @setup_perpcu_clockev:	set up the per cpu clock event device for the | ||||
|  *				boot cpu | ||||
|  * @tsc_pre_init:		platform function called before TSC init | ||||
|  * @timer_init:			initialize the platform timer (default PIT/HPET) | ||||
|  * @wallclock_init:		init the wallclock device | ||||
|  */ | ||||
| struct x86_init_timers { | ||||
| 	void (*setup_percpu_clockev)(void); | ||||
| 	void (*tsc_pre_init)(void); | ||||
| 	void (*timer_init)(void); | ||||
| 	void (*wallclock_init)(void); | ||||
| }; | ||||
|  |  | |||
|  | @ -553,7 +553,7 @@ do {							\ | |||
| 	if (cpu_has_xmm) {				\ | ||||
| 		xor_speed(&xor_block_pIII_sse);		\ | ||||
| 		xor_speed(&xor_block_sse_pf64);		\ | ||||
| 	} else if (cpu_has_mmx) {			\ | ||||
| 	} else if (boot_cpu_has(X86_FEATURE_MMX)) {	\ | ||||
| 		xor_speed(&xor_block_pII_mmx);		\ | ||||
| 		xor_speed(&xor_block_p5_mmx);		\ | ||||
| 	} else {					\ | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ struct mce { | |||
| 	__u8  cpuvendor;	/* cpu vendor as encoded in system.h */ | ||||
| 	__u8  inject_flags;	/* software inject flags */ | ||||
| 	__u8  severity; | ||||
| 	__u8  usable_addr; | ||||
| 	__u8  pad; | ||||
| 	__u32 cpuid;	/* CPUID 1 EAX */ | ||||
| 	__u8  cs;		/* code segment */ | ||||
| 	__u8  bank;	/* machine check bank */ | ||||
|  |  | |||
|  | @ -81,6 +81,12 @@ physid_mask_t phys_cpu_present_map; | |||
|  */ | ||||
| static unsigned int disabled_cpu_apicid __read_mostly = BAD_APICID; | ||||
| 
 | ||||
| /*
 | ||||
|  * This variable controls which CPUs receive external NMIs.  By default, | ||||
|  * external NMIs are delivered only to the BSP. | ||||
|  */ | ||||
| static int apic_extnmi = APIC_EXTNMI_BSP; | ||||
| 
 | ||||
| /*
 | ||||
|  * Map cpu index to physical APIC ID | ||||
|  */ | ||||
|  | @ -1161,6 +1167,8 @@ void __init init_bsp_APIC(void) | |||
| 	value = APIC_DM_NMI; | ||||
| 	if (!lapic_is_integrated())		/* 82489DX */ | ||||
| 		value |= APIC_LVT_LEVEL_TRIGGER; | ||||
| 	if (apic_extnmi == APIC_EXTNMI_NONE) | ||||
| 		value |= APIC_LVT_MASKED; | ||||
| 	apic_write(APIC_LVT1, value); | ||||
| } | ||||
| 
 | ||||
|  | @ -1378,9 +1386,11 @@ void setup_local_APIC(void) | |||
| 	apic_write(APIC_LVT0, value); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * only the BP should see the LINT1 NMI signal, obviously. | ||||
| 	 * Only the BSP sees the LINT1 NMI signal by default. This can be | ||||
| 	 * modified by apic_extnmi= boot option. | ||||
| 	 */ | ||||
| 	if (!cpu) | ||||
| 	if ((!cpu && apic_extnmi != APIC_EXTNMI_NONE) || | ||||
| 	    apic_extnmi == APIC_EXTNMI_ALL) | ||||
| 		value = APIC_DM_NMI; | ||||
| 	else | ||||
| 		value = APIC_DM_NMI | APIC_LVT_MASKED; | ||||
|  | @ -2270,6 +2280,7 @@ static struct { | |||
| 	unsigned int apic_tmict; | ||||
| 	unsigned int apic_tdcr; | ||||
| 	unsigned int apic_thmr; | ||||
| 	unsigned int apic_cmci; | ||||
| } apic_pm_state; | ||||
| 
 | ||||
| static int lapic_suspend(void) | ||||
|  | @ -2299,6 +2310,10 @@ static int lapic_suspend(void) | |||
| 	if (maxlvt >= 5) | ||||
| 		apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR); | ||||
| #endif | ||||
| #ifdef CONFIG_X86_MCE_INTEL | ||||
| 	if (maxlvt >= 6) | ||||
| 		apic_pm_state.apic_cmci = apic_read(APIC_LVTCMCI); | ||||
| #endif | ||||
| 
 | ||||
| 	local_irq_save(flags); | ||||
| 	disable_local_APIC(); | ||||
|  | @ -2355,9 +2370,13 @@ static void lapic_resume(void) | |||
| 	apic_write(APIC_SPIV, apic_pm_state.apic_spiv); | ||||
| 	apic_write(APIC_LVT0, apic_pm_state.apic_lvt0); | ||||
| 	apic_write(APIC_LVT1, apic_pm_state.apic_lvt1); | ||||
| #if defined(CONFIG_X86_MCE_INTEL) | ||||
| #ifdef CONFIG_X86_THERMAL_VECTOR | ||||
| 	if (maxlvt >= 5) | ||||
| 		apic_write(APIC_LVTTHMR, apic_pm_state.apic_thmr); | ||||
| #endif | ||||
| #ifdef CONFIG_X86_MCE_INTEL | ||||
| 	if (maxlvt >= 6) | ||||
| 		apic_write(APIC_LVTCMCI, apic_pm_state.apic_cmci); | ||||
| #endif | ||||
| 	if (maxlvt >= 4) | ||||
| 		apic_write(APIC_LVTPC, apic_pm_state.apic_lvtpc); | ||||
|  | @ -2548,3 +2567,23 @@ static int __init apic_set_disabled_cpu_apicid(char *arg) | |||
| 	return 0; | ||||
| } | ||||
| early_param("disable_cpu_apicid", apic_set_disabled_cpu_apicid); | ||||
| 
 | ||||
| static int __init apic_set_extnmi(char *arg) | ||||
| { | ||||
| 	if (!arg) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	if (!strncmp("all", arg, 3)) | ||||
| 		apic_extnmi = APIC_EXTNMI_ALL; | ||||
| 	else if (!strncmp("none", arg, 4)) | ||||
| 		apic_extnmi = APIC_EXTNMI_NONE; | ||||
| 	else if (!strncmp("bsp", arg, 3)) | ||||
| 		apic_extnmi = APIC_EXTNMI_BSP; | ||||
| 	else { | ||||
| 		pr_warn("Unknown external NMI delivery mode `%s' ignored\n", arg); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| early_param("apic_extnmi", apic_set_extnmi); | ||||
|  |  | |||
|  | @ -185,6 +185,7 @@ static struct apic apic_flat =  { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= flat_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= default_send_IPI_single, | ||||
| 	.send_IPI_mask			= flat_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= flat_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= flat_send_IPI_allbutself, | ||||
|  | @ -230,17 +231,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_sequence_phys(cpumask, vector); | ||||
| } | ||||
| 
 | ||||
| static void physflat_send_IPI_mask_allbutself(const struct cpumask *cpumask, | ||||
| 					      int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_allbutself_phys(cpumask, vector); | ||||
| } | ||||
| 
 | ||||
| static void physflat_send_IPI_allbutself(int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | ||||
|  | @ -248,7 +238,7 @@ static void physflat_send_IPI_allbutself(int vector) | |||
| 
 | ||||
| static void physflat_send_IPI_all(int vector) | ||||
| { | ||||
| 	physflat_send_IPI_mask(cpu_online_mask, vector); | ||||
| 	default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); | ||||
| } | ||||
| 
 | ||||
| static int physflat_probe(void) | ||||
|  | @ -292,8 +282,9 @@ static struct apic apic_physflat =  { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI_mask			= physflat_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= physflat_send_IPI_mask_allbutself, | ||||
| 	.send_IPI			= default_send_IPI_single_phys, | ||||
| 	.send_IPI_mask			= default_send_IPI_mask_sequence_phys, | ||||
| 	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_phys, | ||||
| 	.send_IPI_allbutself		= physflat_send_IPI_allbutself, | ||||
| 	.send_IPI_all			= physflat_send_IPI_all, | ||||
| 	.send_IPI_self			= apic_send_IPI_self, | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ | |||
| #include <asm/e820.h> | ||||
| 
 | ||||
| static void noop_init_apic_ldr(void) { } | ||||
| static void noop_send_IPI(int cpu, int vector) { } | ||||
| static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { } | ||||
| static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { } | ||||
| static void noop_send_IPI_allbutself(int vector) { } | ||||
|  | @ -144,6 +145,7 @@ struct apic apic_noop = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= flat_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= noop_send_IPI, | ||||
| 	.send_IPI_mask			= noop_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= noop_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= noop_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -273,6 +273,7 @@ static const struct apic apic_numachip1 __refconst = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= numachip_send_IPI_one, | ||||
| 	.send_IPI_mask			= numachip_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= numachip_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= numachip_send_IPI_allbutself, | ||||
|  | @ -324,6 +325,7 @@ static const struct apic apic_numachip2 __refconst = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= numachip_send_IPI_one, | ||||
| 	.send_IPI_mask			= numachip_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= numachip_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= numachip_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -96,11 +96,6 @@ static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb) | |||
| 	return cpuid_apic >> index_msb; | ||||
| } | ||||
| 
 | ||||
| static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_sequence_phys(mask, vector); | ||||
| } | ||||
| 
 | ||||
| static void bigsmp_send_IPI_allbutself(int vector) | ||||
| { | ||||
| 	default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector); | ||||
|  | @ -108,7 +103,7 @@ static void bigsmp_send_IPI_allbutself(int vector) | |||
| 
 | ||||
| static void bigsmp_send_IPI_all(int vector) | ||||
| { | ||||
| 	bigsmp_send_IPI_mask(cpu_online_mask, vector); | ||||
| 	default_send_IPI_mask_sequence_phys(cpu_online_mask, vector); | ||||
| } | ||||
| 
 | ||||
| static int dmi_bigsmp; /* can be set by dmi scanners */ | ||||
|  | @ -180,7 +175,8 @@ static struct apic apic_bigsmp = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI_mask			= bigsmp_send_IPI_mask, | ||||
| 	.send_IPI			= default_send_IPI_single_phys, | ||||
| 	.send_IPI_mask			= default_send_IPI_mask_sequence_phys, | ||||
| 	.send_IPI_mask_allbutself	= NULL, | ||||
| 	.send_IPI_allbutself		= bigsmp_send_IPI_allbutself, | ||||
| 	.send_IPI_all			= bigsmp_send_IPI_all, | ||||
|  |  | |||
|  | @ -18,6 +18,16 @@ | |||
| #include <asm/proto.h> | ||||
| #include <asm/ipi.h> | ||||
| 
 | ||||
| void default_send_IPI_single_phys(int cpu, int vector) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 
 | ||||
| 	local_irq_save(flags); | ||||
| 	__default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, cpu), | ||||
| 				      vector, APIC_DEST_PHYSICAL); | ||||
| 	local_irq_restore(flags); | ||||
| } | ||||
| 
 | ||||
| void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) | ||||
| { | ||||
| 	unsigned long query_cpu; | ||||
|  | @ -55,6 +65,14 @@ void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, | |||
| 	local_irq_restore(flags); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Helper function for APICs which insist on cpumasks | ||||
|  */ | ||||
| void default_send_IPI_single(int cpu, int vector) | ||||
| { | ||||
| 	apic->send_IPI_mask(cpumask_of(cpu), vector); | ||||
| } | ||||
| 
 | ||||
| #ifdef CONFIG_X86_32 | ||||
| 
 | ||||
| void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, | ||||
|  |  | |||
|  | @ -96,8 +96,8 @@ static irq_hw_number_t pci_msi_get_hwirq(struct msi_domain_info *info, | |||
| 	return arg->msi_hwirq; | ||||
| } | ||||
| 
 | ||||
| static int pci_msi_prepare(struct irq_domain *domain, struct device *dev, | ||||
| 			   int nvec, msi_alloc_info_t *arg) | ||||
| int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, | ||||
| 		    msi_alloc_info_t *arg) | ||||
| { | ||||
| 	struct pci_dev *pdev = to_pci_dev(dev); | ||||
| 	struct msi_desc *desc = first_pci_msi_entry(pdev); | ||||
|  | @ -113,11 +113,13 @@ static int pci_msi_prepare(struct irq_domain *domain, struct device *dev, | |||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(pci_msi_prepare); | ||||
| 
 | ||||
| static void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) | ||||
| void pci_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc) | ||||
| { | ||||
| 	arg->msi_hwirq = pci_msi_domain_calc_hwirq(arg->msi_dev, desc); | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(pci_msi_set_desc); | ||||
| 
 | ||||
| static struct msi_domain_ops pci_msi_domain_ops = { | ||||
| 	.get_hwirq	= pci_msi_get_hwirq, | ||||
|  |  | |||
|  | @ -105,6 +105,7 @@ static struct apic apic_default = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= flat_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= default_send_IPI_single, | ||||
| 	.send_IPI_mask			= default_send_IPI_mask_logical, | ||||
| 	.send_IPI_mask_allbutself	= default_send_IPI_mask_allbutself_logical, | ||||
| 	.send_IPI_allbutself		= default_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ struct apic_chip_data { | |||
| }; | ||||
| 
 | ||||
| struct irq_domain *x86_vector_domain; | ||||
| EXPORT_SYMBOL_GPL(x86_vector_domain); | ||||
| static DEFINE_RAW_SPINLOCK(vector_lock); | ||||
| static cpumask_var_t vector_cpumask; | ||||
| static struct irq_chip lapic_controller; | ||||
|  | @ -66,6 +67,7 @@ struct irq_cfg *irqd_cfg(struct irq_data *irq_data) | |||
| 
 | ||||
| 	return data ? &data->cfg : NULL; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(irqd_cfg); | ||||
| 
 | ||||
| struct irq_cfg *irq_cfg(unsigned int irq) | ||||
| { | ||||
|  |  | |||
|  | @ -23,6 +23,14 @@ static inline u32 x2apic_cluster(int cpu) | |||
| 	return per_cpu(x86_cpu_to_logical_apicid, cpu) >> 16; | ||||
| } | ||||
| 
 | ||||
| static void x2apic_send_IPI(int cpu, int vector) | ||||
| { | ||||
| 	u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu); | ||||
| 
 | ||||
| 	x2apic_wrmsr_fence(); | ||||
| 	__x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) | ||||
| { | ||||
|  | @ -266,6 +274,7 @@ static struct apic apic_x2apic_cluster = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= x2apic_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= x2apic_send_IPI, | ||||
| 	.send_IPI_mask			= x2apic_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= x2apic_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= x2apic_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -36,6 +36,14 @@ static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
| 	return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); | ||||
| } | ||||
| 
 | ||||
| static void x2apic_send_IPI(int cpu, int vector) | ||||
| { | ||||
| 	u32 dest = per_cpu(x86_cpu_to_apicid, cpu); | ||||
| 
 | ||||
| 	x2apic_wrmsr_fence(); | ||||
| 	__x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) | ||||
| { | ||||
|  | @ -122,6 +130,7 @@ static struct apic apic_x2apic_phys = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= default_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= x2apic_send_IPI, | ||||
| 	.send_IPI_mask			= x2apic_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= x2apic_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= x2apic_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -406,6 +406,7 @@ static struct apic __refdata apic_x2apic_uv_x = { | |||
| 
 | ||||
| 	.cpu_mask_to_apicid_and		= uv_cpu_mask_to_apicid_and, | ||||
| 
 | ||||
| 	.send_IPI			= uv_send_IPI_one, | ||||
| 	.send_IPI_mask			= uv_send_IPI_mask, | ||||
| 	.send_IPI_mask_allbutself	= uv_send_IPI_mask_allbutself, | ||||
| 	.send_IPI_allbutself		= uv_send_IPI_allbutself, | ||||
|  |  | |||
|  | @ -65,9 +65,6 @@ void common(void) { | |||
| 	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable); | ||||
| 	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable); | ||||
| 	OFFSET(PV_CPU_iret, pv_cpu_ops, iret); | ||||
| #ifdef CONFIG_X86_32 | ||||
| 	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit); | ||||
| #endif | ||||
| 	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0); | ||||
| 	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2); | ||||
| #endif | ||||
|  |  | |||
|  | @ -23,7 +23,6 @@ int main(void) | |||
| { | ||||
| #ifdef CONFIG_PARAVIRT | ||||
| 	OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame); | ||||
| 	OFFSET(PV_CPU_usergs_sysret32, pv_cpu_ops, usergs_sysret32); | ||||
| 	OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64); | ||||
| 	OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs); | ||||
| 	BLANK(); | ||||
|  |  | |||
|  | @ -304,7 +304,7 @@ static void amd_get_topology(struct cpuinfo_x86 *c) | |||
| 	int cpu = smp_processor_id(); | ||||
| 
 | ||||
| 	/* get information required for multi-node processors */ | ||||
| 	if (cpu_has_topoext) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { | ||||
| 		u32 eax, ebx, ecx, edx; | ||||
| 
 | ||||
| 		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); | ||||
|  | @ -678,9 +678,9 @@ static void init_amd_bd(struct cpuinfo_x86 *c) | |||
| 	 * Disable it on the affected CPUs. | ||||
| 	 */ | ||||
| 	if ((c->x86_model >= 0x02) && (c->x86_model < 0x20)) { | ||||
| 		if (!rdmsrl_safe(0xc0011021, &value) && !(value & 0x1E)) { | ||||
| 		if (!rdmsrl_safe(MSR_F15H_IC_CFG, &value) && !(value & 0x1E)) { | ||||
| 			value |= 0x1E; | ||||
| 			wrmsrl_safe(0xc0011021, value); | ||||
| 			wrmsrl_safe(MSR_F15H_IC_CFG, value); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -922,7 +922,7 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) | |||
| 
 | ||||
| void set_dr_addr_mask(unsigned long mask, int dr) | ||||
| { | ||||
| 	if (!cpu_has_bpext) | ||||
| 	if (!boot_cpu_has(X86_FEATURE_BPEXT)) | ||||
| 		return; | ||||
| 
 | ||||
| 	switch (dr) { | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ static void init_c3(struct cpuinfo_x86 *c) | |||
| 		/* store Centaur Extended Feature Flags as
 | ||||
| 		 * word 5 of the CPU capability bit array | ||||
| 		 */ | ||||
| 		c->x86_capability[5] = cpuid_edx(0xC0000001); | ||||
| 		c->x86_capability[CPUID_C000_0001_EDX] = cpuid_edx(0xC0000001); | ||||
| 	} | ||||
| #ifdef CONFIG_X86_32 | ||||
| 	/* Cyrix III family needs CX8 & PGE explicitly enabled. */ | ||||
|  |  | |||
|  | @ -581,14 +581,9 @@ void cpu_detect(struct cpuinfo_x86 *c) | |||
| 		u32 junk, tfms, cap0, misc; | ||||
| 
 | ||||
| 		cpuid(0x00000001, &tfms, &misc, &junk, &cap0); | ||||
| 		c->x86 = (tfms >> 8) & 0xf; | ||||
| 		c->x86_model = (tfms >> 4) & 0xf; | ||||
| 		c->x86_mask = tfms & 0xf; | ||||
| 
 | ||||
| 		if (c->x86 == 0xf) | ||||
| 			c->x86 += (tfms >> 20) & 0xff; | ||||
| 		if (c->x86 >= 0x6) | ||||
| 			c->x86_model += ((tfms >> 16) & 0xf) << 4; | ||||
| 		c->x86		= x86_family(tfms); | ||||
| 		c->x86_model	= x86_model(tfms); | ||||
| 		c->x86_mask	= x86_stepping(tfms); | ||||
| 
 | ||||
| 		if (cap0 & (1<<19)) { | ||||
| 			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8; | ||||
|  | @ -599,50 +594,47 @@ void cpu_detect(struct cpuinfo_x86 *c) | |||
| 
 | ||||
| void get_cpu_cap(struct cpuinfo_x86 *c) | ||||
| { | ||||
| 	u32 tfms, xlvl; | ||||
| 	u32 ebx; | ||||
| 	u32 eax, ebx, ecx, edx; | ||||
| 
 | ||||
| 	/* Intel-defined flags: level 0x00000001 */ | ||||
| 	if (c->cpuid_level >= 0x00000001) { | ||||
| 		u32 capability, excap; | ||||
| 		cpuid(0x00000001, &eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 		cpuid(0x00000001, &tfms, &ebx, &excap, &capability); | ||||
| 		c->x86_capability[0] = capability; | ||||
| 		c->x86_capability[4] = excap; | ||||
| 		c->x86_capability[CPUID_1_ECX] = ecx; | ||||
| 		c->x86_capability[CPUID_1_EDX] = edx; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Additional Intel-defined flags: level 0x00000007 */ | ||||
| 	if (c->cpuid_level >= 0x00000007) { | ||||
| 		u32 eax, ebx, ecx, edx; | ||||
| 
 | ||||
| 		cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 		c->x86_capability[9] = ebx; | ||||
| 		c->x86_capability[CPUID_7_0_EBX] = ebx; | ||||
| 
 | ||||
| 		c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Extended state features: level 0x0000000d */ | ||||
| 	if (c->cpuid_level >= 0x0000000d) { | ||||
| 		u32 eax, ebx, ecx, edx; | ||||
| 
 | ||||
| 		cpuid_count(0x0000000d, 1, &eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 		c->x86_capability[10] = eax; | ||||
| 		c->x86_capability[CPUID_D_1_EAX] = eax; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Additional Intel-defined flags: level 0x0000000F */ | ||||
| 	if (c->cpuid_level >= 0x0000000F) { | ||||
| 		u32 eax, ebx, ecx, edx; | ||||
| 
 | ||||
| 		/* QoS sub-leaf, EAX=0Fh, ECX=0 */ | ||||
| 		cpuid_count(0x0000000F, 0, &eax, &ebx, &ecx, &edx); | ||||
| 		c->x86_capability[11] = edx; | ||||
| 		c->x86_capability[CPUID_F_0_EDX] = edx; | ||||
| 
 | ||||
| 		if (cpu_has(c, X86_FEATURE_CQM_LLC)) { | ||||
| 			/* will be overridden if occupancy monitoring exists */ | ||||
| 			c->x86_cache_max_rmid = ebx; | ||||
| 
 | ||||
| 			/* QoS sub-leaf, EAX=0Fh, ECX=1 */ | ||||
| 			cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx); | ||||
| 			c->x86_capability[12] = edx; | ||||
| 			c->x86_capability[CPUID_F_1_EDX] = edx; | ||||
| 
 | ||||
| 			if (cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC)) { | ||||
| 				c->x86_cache_max_rmid = ecx; | ||||
| 				c->x86_cache_occ_scale = ebx; | ||||
|  | @ -654,22 +646,24 @@ void get_cpu_cap(struct cpuinfo_x86 *c) | |||
| 	} | ||||
| 
 | ||||
| 	/* AMD-defined flags: level 0x80000001 */ | ||||
| 	xlvl = cpuid_eax(0x80000000); | ||||
| 	c->extended_cpuid_level = xlvl; | ||||
| 	eax = cpuid_eax(0x80000000); | ||||
| 	c->extended_cpuid_level = eax; | ||||
| 
 | ||||
| 	if ((xlvl & 0xffff0000) == 0x80000000) { | ||||
| 		if (xlvl >= 0x80000001) { | ||||
| 			c->x86_capability[1] = cpuid_edx(0x80000001); | ||||
| 			c->x86_capability[6] = cpuid_ecx(0x80000001); | ||||
| 	if ((eax & 0xffff0000) == 0x80000000) { | ||||
| 		if (eax >= 0x80000001) { | ||||
| 			cpuid(0x80000001, &eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 			c->x86_capability[CPUID_8000_0001_ECX] = ecx; | ||||
| 			c->x86_capability[CPUID_8000_0001_EDX] = edx; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (c->extended_cpuid_level >= 0x80000008) { | ||||
| 		u32 eax = cpuid_eax(0x80000008); | ||||
| 		cpuid(0x80000008, &eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 		c->x86_virt_bits = (eax >> 8) & 0xff; | ||||
| 		c->x86_phys_bits = eax & 0xff; | ||||
| 		c->x86_capability[13] = cpuid_ebx(0x80000008); | ||||
| 		c->x86_capability[CPUID_8000_0008_EBX] = ebx; | ||||
| 	} | ||||
| #ifdef CONFIG_X86_32 | ||||
| 	else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36)) | ||||
|  | @ -679,6 +673,9 @@ void get_cpu_cap(struct cpuinfo_x86 *c) | |||
| 	if (c->extended_cpuid_level >= 0x80000007) | ||||
| 		c->x86_power = cpuid_edx(0x80000007); | ||||
| 
 | ||||
| 	if (c->extended_cpuid_level >= 0x8000000a) | ||||
| 		c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a); | ||||
| 
 | ||||
| 	init_scattered_cpuid_features(c); | ||||
| } | ||||
| 
 | ||||
|  | @ -1185,7 +1182,7 @@ void syscall_init(void) | |||
| 	 * They both write to the same internal register. STAR allows to | ||||
| 	 * set CS/DS but only a 32bit target. LSTAR sets the 64bit rip. | ||||
| 	 */ | ||||
| 	wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32); | ||||
| 	wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS); | ||||
| 	wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64); | ||||
| 
 | ||||
| #ifdef CONFIG_IA32_EMULATION | ||||
|  | @ -1443,7 +1440,9 @@ void cpu_init(void) | |||
| 
 | ||||
| 	printk(KERN_INFO "Initializing CPU#%d\n", cpu); | ||||
| 
 | ||||
| 	if (cpu_feature_enabled(X86_FEATURE_VME) || cpu_has_tsc || cpu_has_de) | ||||
| 	if (cpu_feature_enabled(X86_FEATURE_VME) || | ||||
| 	    cpu_has_tsc || | ||||
| 	    boot_cpu_has(X86_FEATURE_DE)) | ||||
| 		cr4_clear_bits(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); | ||||
| 
 | ||||
| 	load_current_idt(); | ||||
|  |  | |||
|  | @ -445,7 +445,8 @@ static void init_intel(struct cpuinfo_x86 *c) | |||
| 
 | ||||
| 	if (cpu_has_xmm2) | ||||
| 		set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | ||||
| 	if (cpu_has_ds) { | ||||
| 
 | ||||
| 	if (boot_cpu_has(X86_FEATURE_DS)) { | ||||
| 		unsigned int l1; | ||||
| 		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2); | ||||
| 		if (!(l1 & (1<<11))) | ||||
|  |  | |||
|  | @ -591,7 +591,7 @@ cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf) | |||
| 	unsigned		edx; | ||||
| 
 | ||||
| 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | ||||
| 		if (cpu_has_topoext) | ||||
| 		if (boot_cpu_has(X86_FEATURE_TOPOEXT)) | ||||
| 			cpuid_count(0x8000001d, index, &eax.full, | ||||
| 				    &ebx.full, &ecx.full, &edx); | ||||
| 		else | ||||
|  | @ -637,7 +637,7 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c) | |||
| void init_amd_cacheinfo(struct cpuinfo_x86 *c) | ||||
| { | ||||
| 
 | ||||
| 	if (cpu_has_topoext) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { | ||||
| 		num_cache_leaves = find_num_cache_leaves(c); | ||||
| 	} else if (c->extended_cpuid_level >= 0x80000006) { | ||||
| 		if (cpuid_edx(0x80000006) & 0xf000) | ||||
|  | @ -809,7 +809,7 @@ static int __cache_amd_cpumap_setup(unsigned int cpu, int index, | |||
| 	struct cacheinfo *this_leaf; | ||||
| 	int i, sibling; | ||||
| 
 | ||||
| 	if (cpu_has_topoext) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { | ||||
| 		unsigned int apicid, nshared, first, last; | ||||
| 
 | ||||
| 		this_leaf = this_cpu_ci->info_list + index; | ||||
|  |  | |||
|  | @ -114,7 +114,6 @@ static struct work_struct mce_work; | |||
| static struct irq_work mce_irq_work; | ||||
| 
 | ||||
| static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs); | ||||
| static int mce_usable_address(struct mce *m); | ||||
| 
 | ||||
| /*
 | ||||
|  * CPU/chipset specific EDAC code can register a notifier call here to print | ||||
|  | @ -475,6 +474,28 @@ static void mce_report_event(struct pt_regs *regs) | |||
| 	irq_work_queue(&mce_irq_work); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Check if the address reported by the CPU is in a format we can parse. | ||||
|  * It would be possible to add code for most other cases, but all would | ||||
|  * be somewhat complicated (e.g. segment offset would require an instruction | ||||
|  * parser). So only support physical addresses up to page granuality for now. | ||||
|  */ | ||||
| static int mce_usable_address(struct mce *m) | ||||
| { | ||||
| 	if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* Checks after this one are Intel-specific: */ | ||||
| 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT) | ||||
| 		return 0; | ||||
| 	if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS) | ||||
| 		return 0; | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static int srao_decode_notifier(struct notifier_block *nb, unsigned long val, | ||||
| 				void *data) | ||||
| { | ||||
|  | @ -484,7 +505,7 @@ static int srao_decode_notifier(struct notifier_block *nb, unsigned long val, | |||
| 	if (!mce) | ||||
| 		return NOTIFY_DONE; | ||||
| 
 | ||||
| 	if (mce->usable_addr && (mce->severity == MCE_AO_SEVERITY)) { | ||||
| 	if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) { | ||||
| 		pfn = mce->addr >> PAGE_SHIFT; | ||||
| 		memory_failure(pfn, MCE_VECTOR, 0); | ||||
| 	} | ||||
|  | @ -522,10 +543,10 @@ static bool memory_error(struct mce *m) | |||
| 	struct cpuinfo_x86 *c = &boot_cpu_data; | ||||
| 
 | ||||
| 	if (c->x86_vendor == X86_VENDOR_AMD) { | ||||
| 		/*
 | ||||
| 		 * coming soon | ||||
| 		 */ | ||||
| 		return false; | ||||
| 		/* ErrCodeExt[20:16] */ | ||||
| 		u8 xec = (m->status >> 16) & 0x1f; | ||||
| 
 | ||||
| 		return (xec == 0x0 || xec == 0x8); | ||||
| 	} else if (c->x86_vendor == X86_VENDOR_INTEL) { | ||||
| 		/*
 | ||||
| 		 * Intel SDM Volume 3B - 15.9.2 Compound Error Codes | ||||
|  | @ -567,7 +588,7 @@ DEFINE_PER_CPU(unsigned, mce_poll_count); | |||
|  */ | ||||
| bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | ||||
| { | ||||
| 	bool error_logged = false; | ||||
| 	bool error_seen = false; | ||||
| 	struct mce m; | ||||
| 	int severity; | ||||
| 	int i; | ||||
|  | @ -601,6 +622,8 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | |||
| 		    (m.status & (mca_cfg.ser ? MCI_STATUS_S : MCI_STATUS_UC))) | ||||
| 			continue; | ||||
| 
 | ||||
| 		error_seen = true; | ||||
| 
 | ||||
| 		mce_read_aux(&m, i); | ||||
| 
 | ||||
| 		if (!(flags & MCP_TIMESTAMP)) | ||||
|  | @ -608,27 +631,24 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | |||
| 
 | ||||
| 		severity = mce_severity(&m, mca_cfg.tolerant, NULL, false); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * In the cases where we don't have a valid address after all, | ||||
| 		 * do not add it into the ring buffer. | ||||
| 		 */ | ||||
| 		if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m)) { | ||||
| 			if (m.status & MCI_STATUS_ADDRV) { | ||||
| 		if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m)) | ||||
| 			if (m.status & MCI_STATUS_ADDRV) | ||||
| 				m.severity = severity; | ||||
| 				m.usable_addr = mce_usable_address(&m); | ||||
| 
 | ||||
| 				if (!mce_gen_pool_add(&m)) | ||||
| 					mce_schedule_work(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Don't get the IP here because it's unlikely to | ||||
| 		 * have anything to do with the actual error location. | ||||
| 		 */ | ||||
| 		if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce) { | ||||
| 			error_logged = true; | ||||
| 		if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce) | ||||
| 			mce_log(&m); | ||||
| 		else if (mce_usable_address(&m)) { | ||||
| 			/*
 | ||||
| 			 * Although we skipped logging this, we still want | ||||
| 			 * to take action. Add to the pool so the registered | ||||
| 			 * notifiers will see it. | ||||
| 			 */ | ||||
| 			if (!mce_gen_pool_add(&m)) | ||||
| 				mce_schedule_work(); | ||||
| 		} | ||||
| 
 | ||||
| 		/*
 | ||||
|  | @ -644,7 +664,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) | |||
| 
 | ||||
| 	sync_core(); | ||||
| 
 | ||||
| 	return error_logged; | ||||
| 	return error_seen; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(machine_check_poll); | ||||
| 
 | ||||
|  | @ -931,23 +951,6 @@ reset: | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Check if the address reported by the CPU is in a format we can parse. | ||||
|  * It would be possible to add code for most other cases, but all would | ||||
|  * be somewhat complicated (e.g. segment offset would require an instruction | ||||
|  * parser). So only support physical addresses up to page granuality for now. | ||||
|  */ | ||||
| static int mce_usable_address(struct mce *m) | ||||
| { | ||||
| 	if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV)) | ||||
| 		return 0; | ||||
| 	if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT) | ||||
| 		return 0; | ||||
| 	if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS) | ||||
| 		return 0; | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static void mce_clear_state(unsigned long *toclear) | ||||
| { | ||||
| 	int i; | ||||
|  | @ -1100,7 +1103,6 @@ void do_machine_check(struct pt_regs *regs, long error_code) | |||
| 
 | ||||
| 		/* assuming valid severity level != 0 */ | ||||
| 		m.severity = severity; | ||||
| 		m.usable_addr = mce_usable_address(&m); | ||||
| 
 | ||||
| 		mce_log(&m); | ||||
| 
 | ||||
|  |  | |||
|  | @ -129,8 +129,8 @@ void __init load_ucode_bsp(void) | |||
| 	if (!have_cpuid_p()) | ||||
| 		return; | ||||
| 
 | ||||
| 	vendor = x86_vendor(); | ||||
| 	family = x86_family(); | ||||
| 	vendor = x86_cpuid_vendor(); | ||||
| 	family = x86_cpuid_family(); | ||||
| 
 | ||||
| 	switch (vendor) { | ||||
| 	case X86_VENDOR_INTEL: | ||||
|  | @ -165,8 +165,8 @@ void load_ucode_ap(void) | |||
| 	if (!have_cpuid_p()) | ||||
| 		return; | ||||
| 
 | ||||
| 	vendor = x86_vendor(); | ||||
| 	family = x86_family(); | ||||
| 	vendor = x86_cpuid_vendor(); | ||||
| 	family = x86_cpuid_family(); | ||||
| 
 | ||||
| 	switch (vendor) { | ||||
| 	case X86_VENDOR_INTEL: | ||||
|  | @ -206,8 +206,8 @@ void reload_early_microcode(void) | |||
| { | ||||
| 	int vendor, family; | ||||
| 
 | ||||
| 	vendor = x86_vendor(); | ||||
| 	family = x86_family(); | ||||
| 	vendor = x86_cpuid_vendor(); | ||||
| 	family = x86_cpuid_family(); | ||||
| 
 | ||||
| 	switch (vendor) { | ||||
| 	case X86_VENDOR_INTEL: | ||||
|  |  | |||
|  | @ -145,10 +145,10 @@ matching_model_microcode(struct microcode_header_intel *mc_header, | |||
| 	int ext_sigcount, i; | ||||
| 	struct extended_signature *ext_sig; | ||||
| 
 | ||||
| 	fam   = __x86_family(sig); | ||||
| 	fam   = x86_family(sig); | ||||
| 	model = x86_model(sig); | ||||
| 
 | ||||
| 	fam_ucode   = __x86_family(mc_header->sig); | ||||
| 	fam_ucode   = x86_family(mc_header->sig); | ||||
| 	model_ucode = x86_model(mc_header->sig); | ||||
| 
 | ||||
| 	if (fam == fam_ucode && model == model_ucode) | ||||
|  | @ -163,7 +163,7 @@ matching_model_microcode(struct microcode_header_intel *mc_header, | |||
| 	ext_sigcount = ext_header->count; | ||||
| 
 | ||||
| 	for (i = 0; i < ext_sigcount; i++) { | ||||
| 		fam_ucode   = __x86_family(ext_sig->sig); | ||||
| 		fam_ucode   = x86_family(ext_sig->sig); | ||||
| 		model_ucode = x86_model(ext_sig->sig); | ||||
| 
 | ||||
| 		if (fam == fam_ucode && model == model_ucode) | ||||
|  | @ -365,7 +365,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) | |||
| 	native_cpuid(&eax, &ebx, &ecx, &edx); | ||||
| 	csig.sig = eax; | ||||
| 
 | ||||
| 	family = __x86_family(csig.sig); | ||||
| 	family = x86_family(csig.sig); | ||||
| 	model  = x86_model(csig.sig); | ||||
| 
 | ||||
| 	if ((model >= 5) || (family > 6)) { | ||||
|  | @ -521,16 +521,12 @@ static bool __init load_builtin_intel_microcode(struct cpio_data *cp) | |||
| { | ||||
| #ifdef CONFIG_X86_64 | ||||
| 	unsigned int eax = 0x00000001, ebx, ecx = 0, edx; | ||||
| 	unsigned int family, model, stepping; | ||||
| 	char name[30]; | ||||
| 
 | ||||
| 	native_cpuid(&eax, &ebx, &ecx, &edx); | ||||
| 
 | ||||
| 	family   = __x86_family(eax); | ||||
| 	model    = x86_model(eax); | ||||
| 	stepping = eax & 0xf; | ||||
| 
 | ||||
| 	sprintf(name, "intel-ucode/%02x-%02x-%02x", family, model, stepping); | ||||
| 	sprintf(name, "intel-ucode/%02x-%02x-%02x", | ||||
| 		      x86_family(eax), x86_model(eax), x86_stepping(eax)); | ||||
| 
 | ||||
| 	return get_builtin_firmware(cp, name); | ||||
| #else | ||||
|  |  | |||
|  | @ -593,9 +593,16 @@ mtrr_calc_range_state(u64 chunk_size, u64 gran_size, | |||
| 		      unsigned long x_remove_base, | ||||
| 		      unsigned long x_remove_size, int i) | ||||
| { | ||||
| 	static struct range range_new[RANGE_NUM]; | ||||
| 	/*
 | ||||
| 	 * range_new should really be an automatic variable, but | ||||
| 	 * putting 4096 bytes on the stack is frowned upon, to put it | ||||
| 	 * mildly. It is safe to make it a static __initdata variable, | ||||
| 	 * since mtrr_calc_range_state is only called during init and | ||||
| 	 * there's no way it will call itself recursively. | ||||
| 	 */ | ||||
| 	static struct range range_new[RANGE_NUM] __initdata; | ||||
| 	unsigned long range_sums_new; | ||||
| 	static int nr_range_new; | ||||
| 	int nr_range_new; | ||||
| 	int num_reg; | ||||
| 
 | ||||
| 	/* Convert ranges to var ranges state: */ | ||||
|  |  | |||
|  | @ -349,7 +349,7 @@ static void get_fixed_ranges(mtrr_type *frs) | |||
| 
 | ||||
| void mtrr_save_fixed_ranges(void *info) | ||||
| { | ||||
| 	if (cpu_has_mtrr) | ||||
| 	if (boot_cpu_has(X86_FEATURE_MTRR)) | ||||
| 		get_fixed_ranges(mtrr_state.fixed_ranges); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -682,7 +682,7 @@ void __init mtrr_bp_init(void) | |||
| 
 | ||||
| 	phys_addr = 32; | ||||
| 
 | ||||
| 	if (cpu_has_mtrr) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_MTRR)) { | ||||
| 		mtrr_if = &generic_mtrr_ops; | ||||
| 		size_or_mask = SIZE_OR_MASK_BITS(36); | ||||
| 		size_and_mask = 0x00f00000; | ||||
|  |  | |||
|  | @ -482,6 +482,9 @@ int x86_pmu_hw_config(struct perf_event *event) | |||
| 			/* Support for IP fixup */ | ||||
| 			if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2) | ||||
| 				precise++; | ||||
| 
 | ||||
| 			if (x86_pmu.pebs_prec_dist) | ||||
| 				precise++; | ||||
| 		} | ||||
| 
 | ||||
| 		if (event->attr.precise_ip > precise) | ||||
|  | @ -1531,6 +1534,7 @@ static void __init filter_events(struct attribute **attrs) | |||
| { | ||||
| 	struct device_attribute *d; | ||||
| 	struct perf_pmu_events_attr *pmu_attr; | ||||
| 	int offset = 0; | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	for (i = 0; attrs[i]; i++) { | ||||
|  | @ -1539,7 +1543,7 @@ static void __init filter_events(struct attribute **attrs) | |||
| 		/* str trumps id */ | ||||
| 		if (pmu_attr->event_str) | ||||
| 			continue; | ||||
| 		if (x86_pmu.event_map(i)) | ||||
| 		if (x86_pmu.event_map(i + offset)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		for (j = i; attrs[j]; j++) | ||||
|  | @ -1547,6 +1551,14 @@ static void __init filter_events(struct attribute **attrs) | |||
| 
 | ||||
| 		/* Check the shifted attr. */ | ||||
| 		i--; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * event_map() is index based, the attrs array is organized | ||||
| 		 * by increasing event index. If we shift the events, then | ||||
| 		 * we need to compensate for the event_map(), otherwise | ||||
| 		 * we are looking up the wrong event in the map | ||||
| 		 */ | ||||
| 		offset++; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -2250,12 +2262,19 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
| 	ss_base = get_segment_base(regs->ss); | ||||
| 
 | ||||
| 	fp = compat_ptr(ss_base + regs->bp); | ||||
| 	pagefault_disable(); | ||||
| 	while (entry->nr < PERF_MAX_STACK_DEPTH) { | ||||
| 		unsigned long bytes; | ||||
| 		frame.next_frame     = 0; | ||||
| 		frame.return_address = 0; | ||||
| 
 | ||||
| 		bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); | ||||
| 		if (!access_ok(VERIFY_READ, fp, 8)) | ||||
| 			break; | ||||
| 
 | ||||
| 		bytes = __copy_from_user_nmi(&frame.next_frame, fp, 4); | ||||
| 		if (bytes != 0) | ||||
| 			break; | ||||
| 		bytes = __copy_from_user_nmi(&frame.return_address, fp+4, 4); | ||||
| 		if (bytes != 0) | ||||
| 			break; | ||||
| 
 | ||||
|  | @ -2265,6 +2284,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
| 		perf_callchain_store(entry, cs_base + frame.return_address); | ||||
| 		fp = compat_ptr(ss_base + frame.next_frame); | ||||
| 	} | ||||
| 	pagefault_enable(); | ||||
| 	return 1; | ||||
| } | ||||
| #else | ||||
|  | @ -2302,12 +2322,19 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
| 	if (perf_callchain_user32(regs, entry)) | ||||
| 		return; | ||||
| 
 | ||||
| 	pagefault_disable(); | ||||
| 	while (entry->nr < PERF_MAX_STACK_DEPTH) { | ||||
| 		unsigned long bytes; | ||||
| 		frame.next_frame	     = NULL; | ||||
| 		frame.return_address = 0; | ||||
| 
 | ||||
| 		bytes = copy_from_user_nmi(&frame, fp, sizeof(frame)); | ||||
| 		if (!access_ok(VERIFY_READ, fp, 16)) | ||||
| 			break; | ||||
| 
 | ||||
| 		bytes = __copy_from_user_nmi(&frame.next_frame, fp, 8); | ||||
| 		if (bytes != 0) | ||||
| 			break; | ||||
| 		bytes = __copy_from_user_nmi(&frame.return_address, fp+8, 8); | ||||
| 		if (bytes != 0) | ||||
| 			break; | ||||
| 
 | ||||
|  | @ -2315,8 +2342,9 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
| 			break; | ||||
| 
 | ||||
| 		perf_callchain_store(entry, frame.return_address); | ||||
| 		fp = frame.next_frame; | ||||
| 		fp = (void __user *)frame.next_frame; | ||||
| 	} | ||||
| 	pagefault_enable(); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -14,17 +14,7 @@ | |||
| 
 | ||||
| #include <linux/perf_event.h> | ||||
| 
 | ||||
| #if 0 | ||||
| #undef wrmsrl | ||||
| #define wrmsrl(msr, val) 						\ | ||||
| do {									\ | ||||
| 	unsigned int _msr = (msr);					\ | ||||
| 	u64 _val = (val);						\ | ||||
| 	trace_printk("wrmsrl(%x, %Lx)\n", (unsigned int)(_msr),		\ | ||||
| 			(unsigned long long)(_val));			\ | ||||
| 	native_write_msr((_msr), (u32)(_val), (u32)(_val >> 32));	\ | ||||
| } while (0) | ||||
| #endif | ||||
| /* To enable MSR tracing please use the generic trace points. */ | ||||
| 
 | ||||
| /*
 | ||||
|  *          |   NHM/WSM    |      SNB     | | ||||
|  | @ -318,6 +308,10 @@ struct cpu_hw_events { | |||
| #define INTEL_UEVENT_CONSTRAINT(c, n)	\ | ||||
| 	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) | ||||
| 
 | ||||
| /* Constraint on specific umask bit only + event */ | ||||
| #define INTEL_UBIT_EVENT_CONSTRAINT(c, n)	\ | ||||
| 	EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT|(c)) | ||||
| 
 | ||||
| /* Like UEVENT_CONSTRAINT, but match flags too */ | ||||
| #define INTEL_FLAGS_UEVENT_CONSTRAINT(c, n)	\ | ||||
| 	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS) | ||||
|  | @ -589,7 +583,8 @@ struct x86_pmu { | |||
| 			bts_active	:1, | ||||
| 			pebs		:1, | ||||
| 			pebs_active	:1, | ||||
| 			pebs_broken	:1; | ||||
| 			pebs_broken	:1, | ||||
| 			pebs_prec_dist	:1; | ||||
| 	int		pebs_record_size; | ||||
| 	void		(*drain_pebs)(struct pt_regs *regs); | ||||
| 	struct event_constraint *pebs_constraints; | ||||
|  | @ -907,6 +902,8 @@ void intel_pmu_lbr_init_hsw(void); | |||
| 
 | ||||
| void intel_pmu_lbr_init_skl(void); | ||||
| 
 | ||||
| void intel_pmu_lbr_init_knl(void); | ||||
| 
 | ||||
| int intel_pmu_setup_lbr_filter(struct perf_event *event); | ||||
| 
 | ||||
| void intel_pt_interrupt(void); | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ static __initconst const u64 amd_hw_cache_event_ids | |||
| 		[ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */ | ||||
| 	}, | ||||
| 	[ C(OP_WRITE) ] = { | ||||
| 		[ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ | ||||
| 		[ C(RESULT_ACCESS) ] = 0, | ||||
| 		[ C(RESULT_MISS)   ] = 0, | ||||
| 	}, | ||||
| 	[ C(OP_PREFETCH) ] = { | ||||
|  | @ -160,7 +160,7 @@ static inline int amd_pmu_addr_offset(int index, bool eventsel) | |||
| 	if (offset) | ||||
| 		return offset; | ||||
| 
 | ||||
| 	if (!cpu_has_perfctr_core) | ||||
| 	if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) | ||||
| 		offset = index; | ||||
| 	else | ||||
| 		offset = index << 1; | ||||
|  | @ -652,7 +652,7 @@ static __initconst const struct x86_pmu amd_pmu = { | |||
| 
 | ||||
| static int __init amd_core_pmu_init(void) | ||||
| { | ||||
| 	if (!cpu_has_perfctr_core) | ||||
| 	if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	switch (boot_cpu_data.x86) { | ||||
|  |  | |||
|  | @ -523,10 +523,10 @@ static int __init amd_uncore_init(void) | |||
| 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | ||||
| 		goto fail_nodev; | ||||
| 
 | ||||
| 	if (!cpu_has_topoext) | ||||
| 	if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) | ||||
| 		goto fail_nodev; | ||||
| 
 | ||||
| 	if (cpu_has_perfctr_nb) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) { | ||||
| 		amd_uncore_nb = alloc_percpu(struct amd_uncore *); | ||||
| 		if (!amd_uncore_nb) { | ||||
| 			ret = -ENOMEM; | ||||
|  | @ -540,7 +540,7 @@ static int __init amd_uncore_init(void) | |||
| 		ret = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cpu_has_perfctr_l2) { | ||||
| 	if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) { | ||||
| 		amd_uncore_l2 = alloc_percpu(struct amd_uncore *); | ||||
| 		if (!amd_uncore_l2) { | ||||
| 			ret = -ENOMEM; | ||||
|  | @ -583,10 +583,11 @@ fail_online: | |||
| 
 | ||||
| 	/* amd_uncore_nb/l2 should have been freed by cleanup_cpu_online */ | ||||
| 	amd_uncore_nb = amd_uncore_l2 = NULL; | ||||
| 	if (cpu_has_perfctr_l2) | ||||
| 
 | ||||
| 	if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) | ||||
| 		perf_pmu_unregister(&amd_l2_pmu); | ||||
| fail_l2: | ||||
| 	if (cpu_has_perfctr_nb) | ||||
| 	if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) | ||||
| 		perf_pmu_unregister(&amd_nb_pmu); | ||||
| 	if (amd_uncore_l2) | ||||
| 		free_percpu(amd_uncore_l2); | ||||
|  |  | |||
|  | @ -185,6 +185,14 @@ struct event_constraint intel_skl_event_constraints[] = { | |||
| 	EVENT_CONSTRAINT_END | ||||
| }; | ||||
| 
 | ||||
| static struct extra_reg intel_knl_extra_regs[] __read_mostly = { | ||||
| 	INTEL_UEVENT_EXTRA_REG(0x01b7, | ||||
| 			       MSR_OFFCORE_RSP_0, 0x7f9ffbffffull, RSP_0), | ||||
| 	INTEL_UEVENT_EXTRA_REG(0x02b7, | ||||
| 			       MSR_OFFCORE_RSP_1, 0x3f9ffbffffull, RSP_1), | ||||
| 	EVENT_EXTRA_END | ||||
| }; | ||||
| 
 | ||||
| static struct extra_reg intel_snb_extra_regs[] __read_mostly = { | ||||
| 	/* must define OFFCORE_RSP_X first, see intel_fixup_er() */ | ||||
| 	INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0), | ||||
|  | @ -255,7 +263,7 @@ struct event_constraint intel_bdw_event_constraints[] = { | |||
| 	FIXED_EVENT_CONSTRAINT(0x003c, 1),	/* CPU_CLK_UNHALTED.CORE */ | ||||
| 	FIXED_EVENT_CONSTRAINT(0x0300, 2),	/* CPU_CLK_UNHALTED.REF */ | ||||
| 	INTEL_UEVENT_CONSTRAINT(0x148, 0x4),	/* L1D_PEND_MISS.PENDING */ | ||||
| 	INTEL_UEVENT_CONSTRAINT(0x8a3, 0x4),	/* CYCLE_ACTIVITY.CYCLES_L1D_MISS */ | ||||
| 	INTEL_UBIT_EVENT_CONSTRAINT(0x8a3, 0x4),	/* CYCLE_ACTIVITY.CYCLES_L1D_MISS */ | ||||
| 	EVENT_CONSTRAINT_END | ||||
| }; | ||||
| 
 | ||||
|  | @ -1457,6 +1465,42 @@ static __initconst const u64 slm_hw_cache_event_ids | |||
|  }, | ||||
| }; | ||||
| 
 | ||||
| #define KNL_OT_L2_HITE		BIT_ULL(19) /* Other Tile L2 Hit */ | ||||
| #define KNL_OT_L2_HITF		BIT_ULL(20) /* Other Tile L2 Hit */ | ||||
| #define KNL_MCDRAM_LOCAL	BIT_ULL(21) | ||||
| #define KNL_MCDRAM_FAR		BIT_ULL(22) | ||||
| #define KNL_DDR_LOCAL		BIT_ULL(23) | ||||
| #define KNL_DDR_FAR		BIT_ULL(24) | ||||
| #define KNL_DRAM_ANY		(KNL_MCDRAM_LOCAL | KNL_MCDRAM_FAR | \ | ||||
| 				    KNL_DDR_LOCAL | KNL_DDR_FAR) | ||||
| #define KNL_L2_READ		SLM_DMND_READ | ||||
| #define KNL_L2_WRITE		SLM_DMND_WRITE | ||||
| #define KNL_L2_PREFETCH		SLM_DMND_PREFETCH | ||||
| #define KNL_L2_ACCESS		SLM_LLC_ACCESS | ||||
| #define KNL_L2_MISS		(KNL_OT_L2_HITE | KNL_OT_L2_HITF | \ | ||||
| 				   KNL_DRAM_ANY | SNB_SNP_ANY | \ | ||||
| 						  SNB_NON_DRAM) | ||||
| 
 | ||||
| static __initconst const u64 knl_hw_cache_extra_regs | ||||
| 				[PERF_COUNT_HW_CACHE_MAX] | ||||
| 				[PERF_COUNT_HW_CACHE_OP_MAX] | ||||
| 				[PERF_COUNT_HW_CACHE_RESULT_MAX] = { | ||||
| 	[C(LL)] = { | ||||
| 		[C(OP_READ)] = { | ||||
| 			[C(RESULT_ACCESS)] = KNL_L2_READ | KNL_L2_ACCESS, | ||||
| 			[C(RESULT_MISS)]   = 0, | ||||
| 		}, | ||||
| 		[C(OP_WRITE)] = { | ||||
| 			[C(RESULT_ACCESS)] = KNL_L2_WRITE | KNL_L2_ACCESS, | ||||
| 			[C(RESULT_MISS)]   = KNL_L2_WRITE | KNL_L2_MISS, | ||||
| 		}, | ||||
| 		[C(OP_PREFETCH)] = { | ||||
| 			[C(RESULT_ACCESS)] = KNL_L2_PREFETCH | KNL_L2_ACCESS, | ||||
| 			[C(RESULT_MISS)]   = KNL_L2_PREFETCH | KNL_L2_MISS, | ||||
| 		}, | ||||
| 	}, | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * Use from PMIs where the LBRs are already disabled. | ||||
|  */ | ||||
|  | @ -2475,6 +2519,44 @@ static void intel_pebs_aliases_snb(struct perf_event *event) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void intel_pebs_aliases_precdist(struct perf_event *event) | ||||
| { | ||||
| 	if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { | ||||
| 		/*
 | ||||
| 		 * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P | ||||
| 		 * (0x003c) so that we can use it with PEBS. | ||||
| 		 * | ||||
| 		 * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't | ||||
| 		 * PEBS capable. However we can use INST_RETIRED.PREC_DIST | ||||
| 		 * (0x01c0), which is a PEBS capable event, to get the same | ||||
| 		 * count. | ||||
| 		 * | ||||
| 		 * The PREC_DIST event has special support to minimize sample | ||||
| 		 * shadowing effects. One drawback is that it can be | ||||
| 		 * only programmed on counter 1, but that seems like an | ||||
| 		 * acceptable trade off. | ||||
| 		 */ | ||||
| 		u64 alt_config = X86_CONFIG(.event=0xc0, .umask=0x01, .inv=1, .cmask=16); | ||||
| 
 | ||||
| 		alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); | ||||
| 		event->hw.config = alt_config; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void intel_pebs_aliases_ivb(struct perf_event *event) | ||||
| { | ||||
| 	if (event->attr.precise_ip < 3) | ||||
| 		return intel_pebs_aliases_snb(event); | ||||
| 	return intel_pebs_aliases_precdist(event); | ||||
| } | ||||
| 
 | ||||
| static void intel_pebs_aliases_skl(struct perf_event *event) | ||||
| { | ||||
| 	if (event->attr.precise_ip < 3) | ||||
| 		return intel_pebs_aliases_core2(event); | ||||
| 	return intel_pebs_aliases_precdist(event); | ||||
| } | ||||
| 
 | ||||
| static unsigned long intel_pmu_free_running_flags(struct perf_event *event) | ||||
| { | ||||
| 	unsigned long flags = x86_pmu.free_running_flags; | ||||
|  | @ -3332,6 +3414,7 @@ __init int intel_pmu_init(void) | |||
| 
 | ||||
| 		x86_pmu.event_constraints = intel_gen_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_core2; | ||||
| 		pr_cont("Atom events, "); | ||||
| 		break; | ||||
| 
 | ||||
|  | @ -3431,7 +3514,8 @@ __init int intel_pmu_init(void) | |||
| 
 | ||||
| 		x86_pmu.event_constraints = intel_ivb_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_ivb; | ||||
| 		x86_pmu.pebs_prec_dist = true; | ||||
| 		if (boot_cpu_data.x86_model == 62) | ||||
| 			x86_pmu.extra_regs = intel_snbep_extra_regs; | ||||
| 		else | ||||
|  | @ -3464,7 +3548,8 @@ __init int intel_pmu_init(void) | |||
| 		x86_pmu.event_constraints = intel_hsw_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints; | ||||
| 		x86_pmu.extra_regs = intel_snbep_extra_regs; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_ivb; | ||||
| 		x86_pmu.pebs_prec_dist = true; | ||||
| 		/* all extra regs are per-cpu when HT is on */ | ||||
| 		x86_pmu.flags |= PMU_FL_HAS_RSP_1; | ||||
| 		x86_pmu.flags |= PMU_FL_NO_HT_SHARING; | ||||
|  | @ -3499,7 +3584,8 @@ __init int intel_pmu_init(void) | |||
| 		x86_pmu.event_constraints = intel_bdw_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_hsw_pebs_event_constraints; | ||||
| 		x86_pmu.extra_regs = intel_snbep_extra_regs; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_ivb; | ||||
| 		x86_pmu.pebs_prec_dist = true; | ||||
| 		/* all extra regs are per-cpu when HT is on */ | ||||
| 		x86_pmu.flags |= PMU_FL_HAS_RSP_1; | ||||
| 		x86_pmu.flags |= PMU_FL_NO_HT_SHARING; | ||||
|  | @ -3511,6 +3597,24 @@ __init int intel_pmu_init(void) | |||
| 		pr_cont("Broadwell events, "); | ||||
| 		break; | ||||
| 
 | ||||
| 	case 87: /* Knights Landing Xeon Phi */ | ||||
| 		memcpy(hw_cache_event_ids, | ||||
| 		       slm_hw_cache_event_ids, sizeof(hw_cache_event_ids)); | ||||
| 		memcpy(hw_cache_extra_regs, | ||||
| 		       knl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs)); | ||||
| 		intel_pmu_lbr_init_knl(); | ||||
| 
 | ||||
| 		x86_pmu.event_constraints = intel_slm_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints; | ||||
| 		x86_pmu.extra_regs = intel_knl_extra_regs; | ||||
| 
 | ||||
| 		/* all extra regs are per-cpu when HT is on */ | ||||
| 		x86_pmu.flags |= PMU_FL_HAS_RSP_1; | ||||
| 		x86_pmu.flags |= PMU_FL_NO_HT_SHARING; | ||||
| 
 | ||||
| 		pr_cont("Knights Landing events, "); | ||||
| 		break; | ||||
| 
 | ||||
| 	case 78: /* 14nm Skylake Mobile */ | ||||
| 	case 94: /* 14nm Skylake Desktop */ | ||||
| 		x86_pmu.late_ack = true; | ||||
|  | @ -3521,7 +3625,8 @@ __init int intel_pmu_init(void) | |||
| 		x86_pmu.event_constraints = intel_skl_event_constraints; | ||||
| 		x86_pmu.pebs_constraints = intel_skl_pebs_event_constraints; | ||||
| 		x86_pmu.extra_regs = intel_skl_extra_regs; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_snb; | ||||
| 		x86_pmu.pebs_aliases = intel_pebs_aliases_skl; | ||||
| 		x86_pmu.pebs_prec_dist = true; | ||||
| 		/* all extra regs are per-cpu when HT is on */ | ||||
| 		x86_pmu.flags |= PMU_FL_HAS_RSP_1; | ||||
| 		x86_pmu.flags |= PMU_FL_NO_HT_SHARING; | ||||
|  |  | |||
|  | @ -620,6 +620,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = { | |||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */ | ||||
| 	/* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01), | ||||
| 	/* Allow all events as PEBS with no flags */ | ||||
| 	INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), | ||||
| 	EVENT_CONSTRAINT_END | ||||
| }; | ||||
| 
 | ||||
|  | @ -686,6 +688,8 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = { | |||
| 	INTEL_PST_CONSTRAINT(0x02cd, 0x8),    /* MEM_TRANS_RETIRED.PRECISE_STORES */ | ||||
| 	/* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), | ||||
| 	/* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), | ||||
| 	INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */ | ||||
| 	INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */ | ||||
| 	INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ | ||||
|  | @ -700,6 +704,8 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = { | |||
| 	INTEL_PLD_CONSTRAINT(0x01cd, 0xf),    /* MEM_TRANS_RETIRED.* */ | ||||
| 	/* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), | ||||
| 	/* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ | ||||
|  | @ -718,9 +724,10 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = { | |||
| 
 | ||||
| struct event_constraint intel_skl_pebs_event_constraints[] = { | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2),	/* INST_RETIRED.PREC_DIST */ | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ | ||||
| 	/* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), | ||||
| 	/* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), | ||||
| 	/* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */ | ||||
| 	INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f), | ||||
| 	INTEL_PLD_CONSTRAINT(0x1cd, 0xf),		      /* MEM_TRANS_RETIRED.* */ | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */ | ||||
| 	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */ | ||||
|  | @ -1101,6 +1108,13 @@ get_next_pebs_record_by_bit(void *base, void *top, int bit) | |||
| 	void *at; | ||||
| 	u64 pebs_status; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * fmt0 does not have a status bitfield (does not use | ||||
| 	 * perf_record_nhm format) | ||||
| 	 */ | ||||
| 	if (x86_pmu.intel_cap.pebs_format < 1) | ||||
| 		return base; | ||||
| 
 | ||||
| 	if (base == NULL) | ||||
| 		return NULL; | ||||
| 
 | ||||
|  | @ -1186,7 +1200,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) | |||
| 	if (!event->attr.precise_ip) | ||||
| 		return; | ||||
| 
 | ||||
| 	n = (top - at) / x86_pmu.pebs_record_size; | ||||
| 	n = top - at; | ||||
| 	if (n <= 0) | ||||
| 		return; | ||||
| 
 | ||||
|  | @ -1230,12 +1244,21 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) | |||
| 		pebs_status = p->status & cpuc->pebs_enabled; | ||||
| 		pebs_status &= (1ULL << x86_pmu.max_pebs_events) - 1; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * On some CPUs the PEBS status can be zero when PEBS is | ||||
| 		 * racing with clearing of GLOBAL_STATUS. | ||||
| 		 * | ||||
| 		 * Normally we would drop that record, but in the | ||||
| 		 * case when there is only a single active PEBS event | ||||
| 		 * we can assume it's for that event. | ||||
| 		 */ | ||||
| 		if (!pebs_status && cpuc->pebs_enabled && | ||||
| 			!(cpuc->pebs_enabled & (cpuc->pebs_enabled-1))) | ||||
| 			pebs_status = cpuc->pebs_enabled; | ||||
| 
 | ||||
| 		bit = find_first_bit((unsigned long *)&pebs_status, | ||||
| 					x86_pmu.max_pebs_events); | ||||
| 		if (WARN(bit >= x86_pmu.max_pebs_events, | ||||
| 			 "PEBS record without PEBS event! status=%Lx pebs_enabled=%Lx active_mask=%Lx", | ||||
| 			 (unsigned long long)p->status, (unsigned long long)cpuc->pebs_enabled, | ||||
| 			 *(unsigned long long *)cpuc->active_mask)) | ||||
| 		if (bit >= x86_pmu.max_pebs_events) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/*
 | ||||
|  |  | |||
|  | @ -42,6 +42,13 @@ static enum { | |||
| #define LBR_FAR_BIT		8 /* do not capture far branches */ | ||||
| #define LBR_CALL_STACK_BIT	9 /* enable call stack */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Following bit only exists in Linux; we mask it out before writing it to | ||||
|  * the actual MSR. But it helps the constraint perf code to understand | ||||
|  * that this is a separate configuration. | ||||
|  */ | ||||
| #define LBR_NO_INFO_BIT	       63 /* don't read LBR_INFO. */ | ||||
| 
 | ||||
| #define LBR_KERNEL	(1 << LBR_KERNEL_BIT) | ||||
| #define LBR_USER	(1 << LBR_USER_BIT) | ||||
| #define LBR_JCC		(1 << LBR_JCC_BIT) | ||||
|  | @ -52,6 +59,7 @@ static enum { | |||
| #define LBR_IND_JMP	(1 << LBR_IND_JMP_BIT) | ||||
| #define LBR_FAR		(1 << LBR_FAR_BIT) | ||||
| #define LBR_CALL_STACK	(1 << LBR_CALL_STACK_BIT) | ||||
| #define LBR_NO_INFO	(1ULL << LBR_NO_INFO_BIT) | ||||
| 
 | ||||
| #define LBR_PLM (LBR_KERNEL | LBR_USER) | ||||
| 
 | ||||
|  | @ -152,8 +160,8 @@ static void __intel_pmu_lbr_enable(bool pmi) | |||
| 	 * did not change. | ||||
| 	 */ | ||||
| 	if (cpuc->lbr_sel) | ||||
| 		lbr_select = cpuc->lbr_sel->config; | ||||
| 	if (!pmi) | ||||
| 		lbr_select = cpuc->lbr_sel->config & x86_pmu.lbr_sel_mask; | ||||
| 	if (!pmi && cpuc->lbr_sel) | ||||
| 		wrmsrl(MSR_LBR_SELECT, lbr_select); | ||||
| 
 | ||||
| 	rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); | ||||
|  | @ -422,6 +430,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) | |||
|  */ | ||||
| static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | ||||
| { | ||||
| 	bool need_info = false; | ||||
| 	unsigned long mask = x86_pmu.lbr_nr - 1; | ||||
| 	int lbr_format = x86_pmu.intel_cap.lbr_format; | ||||
| 	u64 tos = intel_pmu_lbr_tos(); | ||||
|  | @ -429,8 +438,11 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | |||
| 	int out = 0; | ||||
| 	int num = x86_pmu.lbr_nr; | ||||
| 
 | ||||
| 	if (cpuc->lbr_sel) { | ||||
| 		need_info = !(cpuc->lbr_sel->config & LBR_NO_INFO); | ||||
| 		if (cpuc->lbr_sel->config & LBR_CALL_STACK) | ||||
| 			num = tos; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < num; i++) { | ||||
| 		unsigned long lbr_idx = (tos - i) & mask; | ||||
|  | @ -442,7 +454,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) | |||
| 		rdmsrl(x86_pmu.lbr_from + lbr_idx, from); | ||||
| 		rdmsrl(x86_pmu.lbr_to   + lbr_idx, to); | ||||
| 
 | ||||
| 		if (lbr_format == LBR_FORMAT_INFO) { | ||||
| 		if (lbr_format == LBR_FORMAT_INFO && need_info) { | ||||
| 			u64 info; | ||||
| 
 | ||||
| 			rdmsrl(MSR_LBR_INFO_0 + lbr_idx, info); | ||||
|  | @ -590,6 +602,7 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event) | |||
| 		if (v != LBR_IGN) | ||||
| 			mask |= v; | ||||
| 	} | ||||
| 
 | ||||
| 	reg = &event->hw.branch_reg; | ||||
| 	reg->idx = EXTRA_REG_LBR; | ||||
| 
 | ||||
|  | @ -600,6 +613,11 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event) | |||
| 	 */ | ||||
| 	reg->config = mask ^ x86_pmu.lbr_sel_mask; | ||||
| 
 | ||||
| 	if ((br_type & PERF_SAMPLE_BRANCH_NO_CYCLES) && | ||||
| 	    (br_type & PERF_SAMPLE_BRANCH_NO_FLAGS) && | ||||
| 	    (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)) | ||||
| 		reg->config |= LBR_NO_INFO; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -1028,3 +1046,17 @@ void __init intel_pmu_lbr_init_atom(void) | |||
| 	 */ | ||||
| 	pr_cont("8-deep LBR, "); | ||||
| } | ||||
| 
 | ||||
| /* Knights Landing */ | ||||
| void intel_pmu_lbr_init_knl(void) | ||||
| { | ||||
| 	x86_pmu.lbr_nr	   = 8; | ||||
| 	x86_pmu.lbr_tos    = MSR_LBR_TOS; | ||||
| 	x86_pmu.lbr_from   = MSR_LBR_NHM_FROM; | ||||
| 	x86_pmu.lbr_to     = MSR_LBR_NHM_TO; | ||||
| 
 | ||||
| 	x86_pmu.lbr_sel_mask = LBR_SEL_MASK; | ||||
| 	x86_pmu.lbr_sel_map  = snb_lbr_sel_map; | ||||
| 
 | ||||
| 	pr_cont("8-deep LBR, "); | ||||
| } | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ | |||
| #include <asm/perf_event.h> | ||||
| #include <asm/insn.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/intel_pt.h> | ||||
| 
 | ||||
| #include "perf_event.h" | ||||
| #include "intel_pt.h" | ||||
|  | @ -1122,6 +1123,14 @@ static int pt_event_init(struct perf_event *event) | |||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void cpu_emergency_stop_pt(void) | ||||
| { | ||||
| 	struct pt *pt = this_cpu_ptr(&pt_ctx); | ||||
| 
 | ||||
| 	if (pt->handle.event) | ||||
| 		pt_event_stop(pt->handle.event, PERF_EF_UPDATE); | ||||
| } | ||||
| 
 | ||||
| static __init int pt_init(void) | ||||
| { | ||||
| 	int ret, cpu, prior_warn = 0; | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Ingo Molnar
						Ingo Molnar