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
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
|
@ -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 |
|
@ -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 |
|
@ -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 |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
{
|
||||
*mode = VCLOCK_NONE;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
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" \
|
||||
\
|
||||
_ASM_EXTABLE(1b, 3b) \
|
||||
: [_err] "=r" (__err)
|
||||
#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) \
|
||||
: "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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
#include <linux/types.h>
|
||||
|
||||
/* PAGE_SHIFT determines the page size */
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
|
||||
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
|
||||
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
|
||||
|
|
|
@ -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->config & LBR_CALL_STACK)
|
||||
num = tos;
|
||||
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, ");
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue