mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
merge with xen-unstable.hg
This commit is contained in:
commit
fd5755e2dd
368 files changed
+26280
-11385
No files matched your search
@@ -156,6 +156,7 @@
|
||||
^tools/xenstat/xentop/xentop$
|
||||
^tools/xenstore/testsuite/tmp/.*$
|
||||
^tools/xenstore/xen$
|
||||
^tools/xenstore/xenstore-chmod$
|
||||
^tools/xenstore/xenstore-exists$
|
||||
^tools/xenstore/xenstore-list$
|
||||
^tools/xenstore/xenstore-read$
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16.13-xen0
|
||||
# Fri Jun 30 12:59:19 2006
|
||||
# Fri Jul 28 16:33:47 2006
|
||||
#
|
||||
|
||||
#
|
||||
@@ -92,6 +92,7 @@ CONFIG_EFI=y
|
||||
CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_XEN=y
|
||||
CONFIG_XEN_IA64_DOM0_VP=y
|
||||
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
CONFIG_DMA_IS_DMA32=y
|
||||
# CONFIG_IA64_GENERIC is not set
|
||||
@@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y
|
||||
#
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||
# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
@@ -1513,7 +1516,7 @@ CONFIG_XEN_SKBUFF=y
|
||||
CONFIG_XEN_NETDEV_BACKEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_DEVMEM is not set
|
||||
# CONFIG_XEN_REBOOT is not set
|
||||
CONFIG_XEN_REBOOT=y
|
||||
# CONFIG_XEN_SMPBOOT is not set
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
|
||||
@@ -1523,13 +1526,16 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_PRIVCMD=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
CONFIG_XEN_XENBUS_DEV=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
|
||||
CONFIG_XEN_NETDEV_LOOPBACK=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
|
||||
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
|
||||
# CONFIG_XEN_TPMDEV_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
# CONFIG_XEN_SCRUB_PAGES is not set
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16.13-xenU
|
||||
# Mon May 22 15:05:32 2006
|
||||
# Fri Jul 28 16:32:18 2006
|
||||
#
|
||||
|
||||
#
|
||||
@@ -89,6 +89,7 @@ CONFIG_EFI=y
|
||||
CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_XEN=y
|
||||
CONFIG_XEN_IA64_DOM0_VP=y
|
||||
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
CONFIG_DMA_IS_DMA32=y
|
||||
# CONFIG_IA64_GENERIC is not set
|
||||
@@ -177,6 +178,8 @@ CONFIG_ACPI_SYSTEM=y
|
||||
#
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||
# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
@@ -1380,8 +1383,15 @@ CONFIG_CRYPTO_DES=y
|
||||
#
|
||||
# Hardware crypto devices
|
||||
#
|
||||
# CONFIG_XEN_UTIL is not set
|
||||
CONFIG_HAVE_ARCH_ALLOC_SKB=y
|
||||
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
|
||||
CONFIG_XEN_BALLOON=y
|
||||
CONFIG_XEN_SKBUFF=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_DEVMEM is not set
|
||||
CONFIG_XEN_REBOOT=y
|
||||
# CONFIG_XEN_SMPBOOT is not set
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
|
||||
#
|
||||
@@ -1389,13 +1399,15 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
#
|
||||
# CONFIG_XEN_PRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_UNPRIVILEGED_GUEST=y
|
||||
CONFIG_XEN_PRIVCMD=y
|
||||
CONFIG_XEN_XENBUS_DEV=y
|
||||
# CONFIG_XEN_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_SCRUB_PAGES is not set
|
||||
# CONFIG_XEN_DISABLE_SERIAL is not set
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_XEN_COMPAT_030002_AND_LATER=y
|
||||
# CONFIG_XEN_COMPAT_LATEST_ONLY is not set
|
||||
CONFIG_XEN_COMPAT_030002=y
|
||||
CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16.13-xen
|
||||
# Thu Jun 29 16:23:48 2006
|
||||
# Fri Jul 28 16:33:08 2006
|
||||
#
|
||||
|
||||
#
|
||||
@@ -92,6 +92,7 @@ CONFIG_EFI=y
|
||||
CONFIG_GENERIC_IOMAP=y
|
||||
CONFIG_XEN=y
|
||||
CONFIG_XEN_IA64_DOM0_VP=y
|
||||
CONFIG_XEN_IA64_VDSO_PARAVIRT=y
|
||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
||||
CONFIG_DMA_IS_DMA32=y
|
||||
# CONFIG_IA64_GENERIC is not set
|
||||
@@ -180,6 +181,8 @@ CONFIG_ACPI_CONTAINER=y
|
||||
#
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||
# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
@@ -1519,7 +1522,7 @@ CONFIG_XEN_SKBUFF=y
|
||||
CONFIG_XEN_NETDEV_BACKEND=y
|
||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||
# CONFIG_XEN_DEVMEM is not set
|
||||
# CONFIG_XEN_REBOOT is not set
|
||||
CONFIG_XEN_REBOOT=y
|
||||
# CONFIG_XEN_SMPBOOT is not set
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
|
||||
@@ -1529,13 +1532,16 @@ CONFIG_XEN_INTERFACE_VERSION=0x00030202
|
||||
CONFIG_XEN_PRIVILEGED_GUEST=y
|
||||
# CONFIG_XEN_UNPRIVILEGED_GUEST is not set
|
||||
CONFIG_XEN_PRIVCMD=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
CONFIG_XEN_XENBUS_DEV=y
|
||||
CONFIG_XEN_BACKEND=y
|
||||
CONFIG_XEN_BLKDEV_BACKEND=y
|
||||
# CONFIG_XEN_BLKDEV_TAP is not set
|
||||
# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
|
||||
CONFIG_XEN_NETDEV_LOOPBACK=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND=y
|
||||
CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
|
||||
# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
|
||||
# CONFIG_XEN_PCIDEV_BE_DEBUG is not set
|
||||
# CONFIG_XEN_TPMDEV_BACKEND is not set
|
||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||
# CONFIG_XEN_SCRUB_PAGES is not set
|
||||
|
||||
@@ -0,0 +1,657 @@
|
||||
%!PS-Adobe-2.0 EPSF-2.0
|
||||
%%BoundingBox: 0 0 610 400
|
||||
%
|
||||
% created by bmeps 1.2.6a (SCCS=1.78)
|
||||
%
|
||||
/pstr
|
||||
610 string
|
||||
def
|
||||
/inputf
|
||||
currentfile
|
||||
/ASCII85Decode filter
|
||||
/RunLengthDecode filter
|
||||
def
|
||||
gsave
|
||||
0 400 translate
|
||||
610 400 scale
|
||||
610 400 8 [610 0 0 -400 0 0]
|
||||
{ inputf pstr readstring pop }
|
||||
image
|
||||
r;Qmd6ps=,r^.#_8PW)W:fC4d:Jq*eJka?]JkgnmP"tsM!)EGd%7s,^8OZ0@77fs;
|
||||
77'??705qG4Sf!e6pt0dBlJ$6H@:BtK8,-ULk:B'L4Y6'Lk:B'LAZi1L4b55LA6Du
|
||||
I0Fb9BjEhVr;R-m;-@(3Bk_O*G'831IK"hMI=cm!I=cmrIK"NpI=6EfrcJ3er,r'_
|
||||
rHA*Xrb2IA?VWW\rrbGT86&[h<YAS@?"./K?t*JP@UEMP?XI8M@=hm=@$4oL>KU.P
|
||||
?s?uGrEfn8='8U';G^7f;cEWm%T$&$92/,W:eEo6!<5/JrCmAj;cQlt>52>&>5_TU
|
||||
=+XM*=+XN'<sVf+;c?Oj:/+I^9E%Np8P)EB770F.5smgo+94/a6N0LZ9heG_;cWft
|
||||
rE0#!!*0"rJl'QcJkptoO\bjL#Ydra8P)EB77I&?"@5=;5!8g*%Q6't*ATB46qBjC
|
||||
9i+berDies#ZXl';c-Cf:/6C8Jk^hkJkZ>A:QXo4rs"Q\9heEFlgauZO%i5;8rW'*
|
||||
rt:&I2DR$=.30ck4@D_29hnM`;u9So;Z]fm;#X2j9hg44b"I=Ya\%.Vn4>s,jHtgV
|
||||
I!BaVEH,o8Bk_3g>%QEJ8P+s'R#6KCG]\+KEGoc0BkLjXA_N/87uZW-R?<GaKSG,3
|
||||
J:N#pH?F+JhM2"b$RdA<+>PuC84ZHM;#O;n<E8ur!DuYl:B!t>8qKZt8qKY(8Qc"]
|
||||
Xg"XjQ&q#bMM[(?IsQ-K=^(,_8cP6]YbdeROH,9WM2$Y4H?*\%>3e[Ks/*9:Ybn+b
|
||||
S=,_1P`h&aK6h<Hl8CCN-mocQ1-.]l9jqaG@UWeYB4><7s+3no97fdX8qKY(8Q>_M
|
||||
ZF-X&R$3VkN/NLGJ:)KU>snW`8cOgV[A][aPE:c_Mhm(;I!'726iTYEs-p[8Z`0do
|
||||
SXZ%8QBRAfL44&>s#)bg-mocQ1-@oo8l\nn='Jo.<rc@fs+3mq97ffq92GS@W2lVY
|
||||
Oc5*LJ:;fjG&hM8?:Orf9E0[DX.blBN/3.;IX6<`Ec5Yu7fPqGs-'dtXJDJWQBI>i
|
||||
MMd.@J9u69s#)bg-n,oS1-@oo9%j!_lMlH/JkL\gN(Y,iJ=W=!O,8O?H?O=GChdZt
|
||||
Ame7292#;8SY)8Bs!VPm?qUGg7/r=IX/+AIP)bETK7JFNaa8;R=oUB<0.87b,W7YM
|
||||
8PB*YrqcWrn"3GU5QXKCkPG5V9+(@lPY78@PY78@p%(fWl1t3L!U9FI9*+;Qr(I%h
|
||||
!r:o[fh2A7n*NdIrrW#WY4kQml1mtFn*f[;q>^"Y!U9E39BSs"8FT.Zs*U)uOc+pC
|
||||
H?O:FC2!QX$"-C*84`c.Q'[X,rsNFN?qUGg7/r4?Un@Yd"H%teJ:.@r&UAV@=oUB<
|
||||
0.81`,W7eQ8k]3Zrql]tLDXF&rkATFBGc!gr;QaLrC[OTs//K!s//K!s4/st9*5.n
|
||||
0)S?Ds8O_>9*5.n0)\EIs8O0emJjZd9**Z;n4Nf6p&7Scn*W+%9*YFr++!>S\+iT#
|
||||
s8O]En*W+%9*67Xs8W$>o1K/bs"8mrJkO]g)uk,DOc>0KI<]jPCM79h@Us%W9)hOW
|
||||
s*'QeNV<A\A7]+?s$fEVLRk',QN$mcKn4[Ort9L!GB$ab3&WE<.2F0e4[Vb5s7lTl
|
||||
rr^k4Gk_%6!f&JMrVlj\rC[O6s2@ISs2@ISs04`Z9*5.n+8eb5s8O2/9*5.n+8nh;
|
||||
s8O06UAsdRo1K/bs"a+;!rr9Ur_!8M2XX3Cs8O06UAsdRq+CqlruXm,2E'np!rr9B
|
||||
n4Ni_ruZhcJkO]g2#hcWMi!1>HZsLKCM.0e@:EbS8cMFVs*'?YM>r-RGB.V;B4PKO
|
||||
@Urh;s$]?ULR=KsP`PhD!.b(K'6SA=G&UR`3&`K=.2F0e4\/:Bs7lTmrrT)Pa7fN7
|
||||
f/SQbrr>[i9+[?fj?`&1j?`&1H::K`s8UsT9,.F+hXsPAruXnjs1qA.ruXnjs8UsT
|
||||
9*Fqfs66<X9*OS[p&G%6rC[k)ruXm,s7nECs8UsK92".As5$CArVm$o9A]^KhYp.O
|
||||
d.RG3\4cf#!)*=k"\VMFs8UsT9*P@Vq>]]Sr(@IuruXm,s7nEChZ*W4r_!=mru_7?
|
||||
%SKIAp&F]p9BlJO9;DOUqF^niru_55"5a(XhYp.MhZ*W4r_!=mruZhcJkO]g2?.WL
|
||||
LkgY6I!BdQD/!Tm@U`hR8H2=Us)<[JL];mPG]dtBBkCoU@Ui_8s$fKXJWlCbP)kS"
|
||||
rtK^$FEMbF=8t6=2D6Ts-oaOa925H]rWN9$k:#fjrrYO$s8Vsj./!U$s6'DCs7@C,
|
||||
fDiO^s4'h<s8T@11]RIshZ(827fWK1fDiO^s4.*C$o<hAmRp:2s26#Zru_265QCa*
|
||||
9pPb0/kuBGZ*Q7<s1P?1eP/d<ruW?>s2Co9gJ-)qehc1*859-a+!45Wru]km]r1n\
|
||||
9hkZfS"frG9DqR2s8O08Q2fDffDiO^s4'h<s8O08s8O1gs40!_b"0)CbtH[g]JfX[
|
||||
(B=CV92!n:]VkeZ9@s3VVuP7>9E5#6JkL\gf1S%%Ck%(jK7A8nF`MA8B4YR^@pMS(
|
||||
92#;$ItNFSIscK`Ec,Z*AcH4L>t4ic8H4.!P*;#gN/@Q6!do9;rcJ`h<rY9C2_QTu
|
||||
-oaOa9i1lbrWE3#8@S0i"5bO$s8,PBhZ'k\S,]bneh^(truX`1q*@dUruX^$s8VEb
|
||||
bo]DMs8O2;ruX`1q*@d4qYpL#2bs5L+%?50+8nr!s8O1,nG.Ap:B1>97S*CU+%H;+
|
||||
5u.I[+&;\4+%?5*5P>$u5u'R1:B1>9:/:ih+8Z!Z7fW9M:B1>99E5#QrD"[=ru[Qr
|
||||
q0G:%ruX`1q*@dUruY#9ru^q6+$iXb6Vd:E61t8(7Jfgqs8O09:AXu47fW9MqYqX,
|
||||
s7nrUs8O0m:4c6m:,W&bH\$d"J:2`gF`D;6B4PL\>"&Bc:B,!SJV*oPI<p-\EGfN(
|
||||
s'oJ@7/ohMs*BQaOcb]ar;RIXH$4=PCfLEr4#\]A)C[d892/7_q#1?pT4%0g!f)%#
|
||||
qbT8is5`eop#Q.X5Z%L\+&N";02V]K+&Gf6s7u]U78Qh\ru_:@+&N";0C&SN0E;%o
|
||||
;#gP;;#gP;rD<Im($(c9:/Luj+&Gf6ruY);s"@4KruY)7rrXqSru_/8(B=CV:f.2l
|
||||
+92?_;#gPK;#gP;;#gP;rD<Im($(c9:B1>9;#gPK;#gP;;#gP;s8O2=:^4i;\c:h7
|
||||
:A[j's8O0;;#gP;;#gPKs8O0;s8O`Ks8O0m;!:`-:@M"8s'p5#J:W6"H[9mXE,96"
|
||||
@piD+s%Z>h@s39Ns+#QFH?XIMCh`oZ?s#er9M5>.L5_1SNrK%pL]@DJH?XLPBiG$r
|
||||
5!(PO*%<s992JOdq#1?p)!Chs!P_M2,lhHOrrF8"qboJBs8Uh2huE_&92k]e+&i48
|
||||
+&i4>+&c,<s,5h8`D]_8ru_+;+&i48+92?_9E5#6;u6M9;uck>rDNass8F)U5YtBX
|
||||
s8O0>;u6M9;ucY8;uck>;u6Ol*s2<=+8f%Qs8O0>;uck>qYqX9s7ma8s8O0>s8O2>
|
||||
;ZZpurZ;h>:fI5j+&i48+&i4>+&i4>+8Z!ZqbmXjs8T>dqG7t-ruY'6qYqX6s7mc5
|
||||
ruY);q&`H5ruZhhJl(&q"TMhJH%#Ph-ZO$=An,.I5lXYWs'K_jIK+bEH[0gYEGfOk
|
||||
@pW/#s%H,dF+T7.NrK%[M2-fart0HsE+`#I5<h4c/0$3&6V10Rrr3#urqucs^Hh_s
|
||||
#JU6=,p`Nk;>^@oG_c,p2td3U6c8rp+&Z(ks09fJbqN,sruY3>s8O0;q>$4RqYqYj
|
||||
s09fJbqS&TMp25$McAU6]N"q2+8o.?s8O2<<&XdV+&l4ms09fJbqN,nruY4gs2E4Y
|
||||
fi6E"`DksP<)i_o+&l5>ru]qoZ-<6m0NA)P+&r:?+8o.?s8O2=<#"$cZ-<6m0N@oK
|
||||
+&r:?+4C2.<9;g4<!:YLruXr2<#5N6+&l4ms09fJbqRiNZ-<6m0N@oK++dID<7b(P
|
||||
s&s2[H2@OfEc,W(?s6Djs&;tt>&/5*s*K*=H?XOQDJK2Z>#@H_:/(\*I>*OWrre18
|
||||
L4t6YrtBHkA5E4n6U*Xf*%X0?9i=nP2`CLk!IoUsrs1^e4S/T;!%#DXrrKT"qGmjZ
|
||||
s*@D/s40..<\3),s48>_<r`1A<`]8#+'-)Ti)IDc]N3kgs48>_<o*f/h>aBO<pBYW
|
||||
s8O2><W`=$+8](?s8O2?<\WA0s48>_<lP+=<`[TCs7MXI<m^F;p7=cT`W,s=<r`1A
|
||||
<o*fUf,mL`s8O0As8O2><W`=$+8](Wh>dN,+%KAFq7Kc.ruY:go)JET7oiZ[s4/:f
|
||||
<W`=$+9#:Ph>dN,+%KAfs8U[m7om>!]Rj2J<e=<?<!<5%Ao;_erss*eC1UaR9fi;R
|
||||
<<$!2DKPUP1LF3X3r`&Qs(ck0L!K^RLPCM8J:@O>EGJrUs$T7>3\MI%4%;tC;c?Rn
|
||||
<*!+(=]\a6TDecljs:#&rr2uBqYpW;3$8!$#"Th<>?Dt<rEB@p+!4,S>6,ffr`]mT
|
||||
+'VrJ+%9C41/D+F+!4,S>7=%E8k:%&>?aB83?K@@>6,ffqHEtB+8oCG808pGr`^IA
|
||||
+!4]k9JR\M<a/d%3?L7^>?arH+'Vqk+'Vr?+!4,S>6Q)j>?`0kr*'1D+8T1D808pG
|
||||
r`^"61/D*r+'VrC3?L7^>?eN8Vb$Se!?WE^>6@D<+%lN:"%XLU9)`#r;_h.#>No@D
|
||||
=7B8os&39<DZ"JdE,TQ-ARSeB8icoQ=8u3+BQ!`f'6%l+C1UgX<(]1N<)N[.F*`@g
|
||||
KDpHHJU`)oGB7Y8?;(;g6pj!j*%!a::/b.o=^,3>?smDP@T]Q,rr^IF!6k0:!T,#O
|
||||
>M<9as8Va6;hA5*>I[l@s%QU'ASD!U&SGZa?WpH+7Q19N>Q7E"?tF$LBfKa:@UE;=
|
||||
:e!AC<)im,CiaiII!U-dH?j^VEG]E#>"AT_7moBn*%!a::/b(k=]o$;?X[AP@VD,,
|
||||
rr^IF!5J7-!P^mO?.rQes5&Yo?%Q:4>I[lqls!.]='Ad1>$>'3=&i0p9Lh<?s'&^o
|
||||
>>.pr>$>'4>$5!0<Du[e7mBZH=&eO&?t<tfChmkdCER>)AR]"N;Hj)m7moBn)C@O8
|
||||
:/Fkh='&O/?!grI@>B+*rrOJHFT2:A,s7t#rrK<"Jm6o4!Zsj3Jm3h2[p)gtfi1+$
|
||||
6:4%+6UF((5<V(h2bVbg>?dEH<'<Q76U=(,6:!k$4Zb\`9@oD0<0Q*H9Mn\c;,^Ck
|
||||
;Gg:d9he2_g5eir6om(A-9F[l:ejhd<)m((r`]G0a#O"s#\*i7L!4$,-0G.*!FVOO
|
||||
=k-Z,=+XM`<rlHgnc&g[PZ_'h=d8IV#4.OR<)HSVnc''aO%Mo16TQt@-9F[d9)_Nd
|
||||
:f:3j<s2Z/s!ZLsrr>1Z!!&elrrVp3mt+Mj<.\)$<97'h;,gCg:ejb]:JOSU9M.qU
|
||||
9En*Z8k_iI8,G[^3\hU#4$,hk5!M:tr^6ZR"%WC+5l:QaPYjPb^\e$4BUAaN7Y4+#
|
||||
7Y3qK5ljABqEY0I4[&a+!BiRE4V9e>4?>M_3]B#W4$#,8-9F:Wr]U?I5PdVIs8Qc!
|
||||
o)Ag43<0#15LhuM5(YtM54UlB4#8W3,rf7*p#lPYs7[r!o`#'_0\?@)K'7gMK'7gM
|
||||
`omXq3[Pak3+#APkl1S`cR>.RrrTYX\,QDZk^r#Mk^r$<kQaL:-5n0i?VL.VrVlug
|
||||
BK4W?rr_Fl8E]sOK'7gMK'7gM`omXq3[Pak3+#APkkkAea!`WkLVJn"5T$-js+9Hd
|
||||
k^r#Mkf2fk6olY5,rf7*p#u5O#1%dD5]D4fq>^6R!!'dt!!%W7K'7gMPir??3[Pak
|
||||
3+#AVkkkD_kQ'fHmcaQKr9+7`kQ'fHo&p&RroaC`kQ'c/!!)u]!!)lZ!!%W7K'7gM
|
||||
Pir??3[Pak3+#AVkPtVZkPtVNkPtVXkPtV^kPtVRkPtV^kPtVDkPtV]kPtVZkPtU7
|
||||
k^r#Mk`k996olY5,rf7*qre"[r9+7`kQ'i1rW)QR!!)o[r;Zo_!9jC^o]Q8TroaIb
|
||||
kQ'i1rW!5fkQ'i1!9iVHo]Q8TrTF:_kii!G"6eqKkktL5k^r#MkaCW>6olY5,rf7*
|
||||
qrmqX"m>sM!9aF^kPtVTkktJ_ki`$GkQCnL!9aFQkQ_+O!9iVHkQ(VG#QX&gki`$1
|
||||
kQ(8=qZ$Z\!<20b!9aFH!<20^!.sEdk^r#ekQaL:-5n0i?VL@\!!)r\!s%NbkkkGQ
|
||||
kPtV\kPtV^kQCnL!9aFQkQV%N!9iVHkkkDckQ'fHkQ'fHo]Q8TrTF7^kkkD_kQ'fH
|
||||
roa=^K'7gMK'8Ze#=LU")C7@M9`+#R!;u$`!9aFH!:]1P!;u$\!<20b!9aFH!:f7X
|
||||
!9aFHkQ'fHr9+=bkQ'fHkQ(8=!!)u]!W_Ear9+1^kQ(VG!!%W7K'7gMRcjuE3[Pak
|
||||
3+#AVkPtV\kQCnL!9aF^kPtVTkPtV\kPtV^kQCnL!9aFPkPtV^kQ1bJ!<20a!9iVH
|
||||
roa=^oB6/SrTF:_kQ(VG"9@WckQ(VG!!%W7K'7gMRcjuE3[Pak3F>JWkPtV\kQCnL
|
||||
!9iYG!;#FP!!2<Ir;[#b!9iVH!:o=R!<20`!9iYG!<20^!<20^!;#CS!<)*_!9iYG
|
||||
!!DHK!9j@]K'7gMK'8Wd#=LZu)C7CN9T\H<!.sEdk^r#akQaL<+rVaf?VL@\qZ,sG
|
||||
qZ,mEqZ,aAq>g?T!!%W7K'7gMQKSQA4<b[i3F>I3k^r#Mk^r#nkQaL<+rVaf?VH(8
|
||||
K'7gMK'8un#=LZu)C7CN9S2J[k^r#MkbI>H6p)Y3,ro=+K'7gMK'7gMUZ_qN4<b[i
|
||||
3F>I3s+:9&s+:9Grs(qS+rVaf?VH(8K'7gMK'8un#=LZu)C7CN9S2J[kecQKs+9Hd
|
||||
kkXEI6p)Y3,ro=+K'7gM_W^:bK'7gMq</&O4<b[i3F>I3k^r$8kj&2"k^r$okQaL<
|
||||
+rVad?VH(8K':)8qYpWcT2>MP!_A[@qYu02K'<$o#=LZu)C7=L9S2J[kecQ\rr\#n
|
||||
@'BRE"Li%]Gk_.9K'7gMq</&O4<b[i2d]71k^r$8kl(M`f/S$Lq>UMO0ZX.lK'7gM
|
||||
q</&O4<b[i2d]71k^r$8kl1S`V_H0brrUe3L]7=*k^r$okQaL<+rVad?VH(8K':)8
|
||||
"TSMb..?d-"$jX$s+9HdkkXEI6p)Y3,r]1)K'7gM_WV+%s%'Wirr_.,p]#j/K'<$o
|
||||
#=LZu)C7=L9S2J[kecNbs.<]grrRt#s+9HdkkXEI6p)Y3,r]1)qWNOVK$MK`!rj,#
|
||||
r;Qb=r?VGRqYpR=htcJfcAKmIchci16p)Y3,r]1)qre(+d":J5kfW)i^Hh_s#BTqG
|
||||
4='t-A,H9,G_c.Z!RB&Dk_nX*dE_XQ#=LZu)C7=L9`4)Tcd7:-K':>?!IoUsrs)CI
|
||||
PlLb\!'L/Y!OkVskQ0#VK'8'T!R]6kkQaL<+rVad?VLC]!7$2[K'3=#jPJYOg?R2h
|
||||
@%[5o"2@\54T#-Za#Nt[!7$2[TBH@;hV7n\rmh#%"5DVfjSe9Bchuu36p)Y3,rT+(
|
||||
r9+.+K'7gM"R+_#N_@VN!Ec8trs.\.,p`O;!'L/Y!T,$skQ&n[kb%&@hVaDeoe6J5
|
||||
J)fPekQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$gl?O$c2RfXQi-jg,lg&]b_6$Zqu6]3
|
||||
5l9aFc@Y8PkQ9P"8+Y^A7ul[/kQ&p+kQaL<,8qjd?VLC]!7$2[K'3=#ge5i7rW.e!
|
||||
rVm/I!%$e-s'l$kqu6]#;#BGVc@Y8PkRuZDd*P)*6-qpE6-qpE6-qpE9DmuRcMZl2
|
||||
6p)\4,rT+(r9+.+K'7gM!pJAmrqt(=!QR1urs6gK!0mMY,lf7grrHN"qre%*K'8ij
|
||||
"PYWV62^HR"4#4Hli$#IcMZl26p)\4,rT+(r9+.+K'7gM"6eMoqTSa:s!ZLtrs(Xd
|
||||
!$qV-!%%RC!r!Q#qre%*K'8ij"5GTSc1Ul75KkhJrTF7,r9+AR4<kaj2IB/UkQ&n[
|
||||
k^r""khIl8pB(B05lCWeF?F'Js+Q0urVlq4QiHsH!7$2[TBHC40Zc6HpB:34atW2\
|
||||
kQ&p+kQaL<,8qjd?VLC]!7$2[K'3:"gb?qE"98C7Qh(.Ya#O,!qre%*K'8ij"5GTN
|
||||
a7f0/oJFWCm/?,JcMZl26p)\4,rT+(r9+.+dHCT2!:/hL!!)3G!!&>KquHNU!<<,r
|
||||
kQ(Y`lf\B)0['+ls8VgAht6pOmkEAns82![cFW3?!!(O4!<<,ikQ(Y`gZSY<!7L'5
|
||||
gb?Z&rUp*hrq-Ed_o"1prTF7,r9+AR4<kaj2IB/UkQ&p&kkbA=kQ(Y`nE9lQ!<20_
|
||||
!!)3G!!)o[qZ,O;!<<,ZkQ(Y`qWReVp#lPZ!9iVH!;Pa]!!)6H!!*#^!<<,ckQ9Nn
|
||||
p%n:]!!*#j!!)BXquH?\rr3&G.$sZ-!k0Serr;lZ!7'KcqZ,gC!<<-!kQ(Y`l0/!E
|
||||
o&p)S!:f7R!!)BLqZ-?R!<<,JkQBTo_86-C$ig;"oDem`o^aoU0^Sc%!7(N+#=L[!
|
||||
)C7:K9`4)ScM6T(!!)u]!<<,GkQ(Y`j6-ICqWIq[!<20_!!(s@!<<,ZkQ(Y`qWIq[
|
||||
!<20_!!)`V!<<,hkQ(Y`k3)m%0_P;7rW!#loDn:N!<<-!oDnplo^r+^"7Kn_fD>LL
|
||||
k?pjDrVucY!7'Kc!<<-!kQ(Y`ki`$I!9E>E!!)HN!<<,RkQ(Y`roa@_!;G[X!!(I2
|
||||
"5GTH2#d+U!!)Z`!!)Z`o>/6sm/?,JcMZl26p)\4,rT+(r9+.+puh_Y!<)*f!!)3_
|
||||
!9aC_kihmDroj:\"R,%L!9jC^"R,%L!9j:[roj:\!U/bF!!MKc!9iYE!!MNL!!)6^
|
||||
!;G[W!;bm[!!)u]!rr>bkkkD`ki`!Hkl(S\kktJdki`!HkPtVHqu?`\qu?`\rW)r]
|
||||
qu?l`kPtVHrVuu_kkkGYkQ(Y`rTF=`!9iYE!!2<Ir;[&c!!)3_!9jC^"R,%L!9j=\
|
||||
"R#gckihpE"R,%L!9jC^qWJ%:0_G#7oDJXko)SCRr;[/qo)Jd^!!)Tj!<)Ki!!*#i
|
||||
#QOkr!!)TjoCMk[!;$*f$HFPKItte"Im=jCqu?QW!7'Kc!<<-!kQLqdki`!HroaLc
|
||||
!9aC_kl(SXkkkD_kPtVHqu?`\rW)r]quHWX!<<,tkQ_(fki`!HkihsF#3b7N!9aC_
|
||||
roaFa!9iYF!!VTM!!)6Hqu?l`kPtVHrW)iZ!<<-!kQLqdki`!HroaOd!9aC_kihpE
|
||||
roj:\i919u0YP0so)Sgkrpp9`1qk[1rTF7,r9+AR4<kaj2IB/UkQ&p'kQ(Y`rTF:_
|
||||
!9j=\!pBUaroaIb!9iVHroaC`!9jC^#3b7N!9aC_r9+7`!9iVHroaLc!9iVH!<20b
|
||||
!!)3_!<20`!!)6^!!DHK!!)iY!!)iY!<<,ukQCkckPtV^kQ1_akl(Pdki`!Hki`$G
|
||||
kQ1_akkkD_ki`!Hroaaj!9iVH!9iVH!9aC_roaC`!9jC^#O(@O!9iVH!;bm[!!)u]
|
||||
"98Gc!!*#^$31(ikPtVHkPtVHrW!;hkPtVH!!)6H!!*#^"98Gc!!*#^!WW5arW!&a
|
||||
kPtV[kQBTooCMkM!<D]h!"\W#!:o[\!:g*inc/[\!!)ug!<<-!ncAdko)/Onnc/[\
|
||||
nc/[\q>UZFIs=4tJ%tgZqre%*hrk(@!<20c!!)6H!!*#^!WW5arW!&akPtVYkQ(Y`
|
||||
roajm!9aC_ki`!Hki`!HkPtV^kQ(Y`r9+.]!;u$d!!)6H!!)3_!<20d!9aC_kPtV^
|
||||
kQCkckPtV^kQV%N!!)3_!<20`!!)6^!!DHK!!)r\!<<-!kQLqdki`!HroaRe!9aC_
|
||||
kPtV^kQCkckPtV^kPtVAkQBTo\ki7p!<<,unc\Ko\hNLLkQ&p+kQaL<,8qjd?VLC]
|
||||
!7(B'!<<,ukQCkckPtV]kQ(Y`roa@_!;ks_!!)3_!<20b!!)3_!<)*^!!)lZ"TSPd
|
||||
kPtV^kQCkckPtV^kQCkckPtV^kQ(Y`q<.eYq<.hZ!<)*a!!)3_!<20b!!)3_!<20_
|
||||
!!)o["98Gc!!)r\!<<-!kR7Fkki`!Hki`!HkPtV^kQCkckPtV^kQLqdki`!HqWIq[
|
||||
!<)*a!!)3_!<20j!!)6H!!)6H!!)3_!<20f!!)3_!9iVH!<20b!!)3_!<20b!!)3_
|
||||
!<20_!!)o["5GU%oDA([!:o^[!!)Te!!r,q!:g*inc/[gnc8^jrpg0l!:g*irpg3m
|
||||
!:o[\!;c6hna,?km/?,JcLg<#cJRj_!<20_!!*#^"98Gc!!*#^!WW5aqu?i_kPtV^
|
||||
kRRXnkPtVHkPtVHkPtVH!!*#^!<<,tkkkG[kktJ`ki`!Hr9+7`!9aC_roaC`!9jC^
|
||||
rTF@a!9aC_roaIb!9aC_roa@_!;u'X!<20_!!*#^#64bf!!)3_!<20`!!)6^!8coA
|
||||
gb?=Nr:0jg!<)HknPHeNm/?,JcMZl26p)\4,rT+(r9+.+puh_Y!<)*a!!)3_!<)*^
|
||||
!!*#^!rr>bkkb>]kPtV^kQCkckPtV^kQ(Y`rTO+Y"6eqK!<20b!!)3_!<20b!!)3_
|
||||
!<20_!!)lZ!!)fX!<<,ukQ1_akkY8\kPtV^kQ:ebkihmD!pBUar9+.]!<20h!!)6H
|
||||
!!)6H!!)6Z!!;?a!<20c!!)6H!!)lZ!<<,ukQ1_akkY8dki`!Hki`!HkPtV^kQh.g
|
||||
kPtVHkPtV^kQCkckPtV^kQCkckPtV^kQ(Y`qre.;0_=o5nc/[hncSpmnc/[fo(`:a
|
||||
nc8^jrpg0l!:g*irpg3m!:o[\!;c6hna,?km/?,JcLg<#cJRgg!!)3_!<)*^!!*#^
|
||||
"98Gc!!*#^!<<,qkQ(Y`roadk!9aC_ki`!Hki`!HkkY;WkQ(Y`qWIq[!<20_!!)r\
|
||||
"98Gc!!*#^!rr>bkktJcki`!HkPtV^kQCkckPtV^kQ(Y`r9+7`!9aC_rTF7^!<20c
|
||||
!!)3_!9j7Z!U/bG!9!&Cgb?0>p@8@V\$e!WrTF7,r9+AR4<kaj2IB/UkQ&p'kQ(Y`
|
||||
rTF@a!9aC_rTF7^!<20b!!)3_!<20b!!)3_!<20f!!)3_!9iVH!<)*^!!*#^"TSPd
|
||||
kPtV^kQCkckPtV^kQCkckPtV^kQ(Y`qWInZpuh_Y!<)*a!!)3_!;ks\!!*#^"98Gc
|
||||
!!*#^"98Gc!!)r\!<<-!kR7Fkki`!Hki`!HkPtV[kQ(Y`roaLc!9iVH!;bm[!!)u]
|
||||
"98Gc!!)lZ#QOkgkPtVH!!*#^#QOkg!!)6H!!*#^"98Gc!!*#^"98Gc!!*#^!<<,s
|
||||
kQBToo()\J!!)uf!s%ik!;l9i!!)QZ!!)re!<<-!nH8glnGiRgnHAmmnaQSZqXF^X
|
||||
lf9bdrTF7,o]Q;#hrk4D!9iVH!<20_!!*#^"98Gc!!*#^!<<,qkQ(Y`roajm!9aC_
|
||||
ki`!Hki`!HkPtVWkQ(Y`qrmtY"6eqK!;u$`!!)3_!<20_!!)u]rW!,c!!)3_!<20b
|
||||
!!)3_!<20_!!)r\"TSPdkPtV^kQ(Y`roaRe!9aC_kPtVXkl(S@kQBToZa9T"!<<,u
|
||||
nHA>`ZS:bEkQ&p+kQaL<,8qjd?VLC]!7(B'!<<,ukQCkckPtV]kQ:ebkii!G!pBUa
|
||||
roaIb!9aC_roaRe!9aC_kPtV\kQ(Y`roaLc!9iVH!<20b!!)3_!<20b!!)3_!<20_
|
||||
!!)o[!!)cW!<<-!kQLqdki`!HrTF=`kPtV^kQCkckPtV^kQCkckPtV\kQ(Y`roaaj
|
||||
!9iVH!9iVH!9aC_rTF=`kPtV^kQLqdki`!HqWIq[!<20c!!)6H!!)u]$NTDS!!)6H
|
||||
!!)3_!<20f!!)3_!9iVH!<20b!!)3_!<20b!!)3_!<20_!!)o["5GU$o)%qW!<)Eh
|
||||
!:fUW!!i&a!!)QZ!!)odqu?ihnGiRfnb`C`nHA@Ij=os!kQ&p#kQ&ockQ(Y`roaRe
|
||||
!9iVH!9iYG!!;?a!<20_!!)iY!<<-!kRRXnkPtVHkPtVHkPtVH!!)u]!!)r\!<<,t
|
||||
kQh.gki`!HkPtV^kQh1P!!)3_!9iYG!!29`roaRe!9aC_kPtV^kQCkckPtV^kQ(Y`
|
||||
r9+.]!<20e!!)6H!!)6HrW!,c!!)3_!<)*_!9aF^kQ(Y`iTLC!0XFjYnGrUirUC$[
|
||||
['MIQrTF7,r9+AR4<kaj2IB/UkQ&p&kkb>^ki`!Hr94+["R#gckihmD!pBUaroaLc
|
||||
!9aC_kkb>\kihmDroj=]"R#gckihpE"6eqK!<20_!!)o[!!)cWqZ-TYqu?c]kkbAZ
|
||||
kkb>]kPtV[kl(PjkPtVHkPtVHkPtVHkkkD_ki`!Hroa@_!<23]!;u'X!<)-Z!<20f
|
||||
!!)6H!!)3_!<20b!!)3_!<23]!!MKc!9iYE!!DHK!!*#^!<<,skQBTonaXuq!<<,r
|
||||
n-&4Fj"TiukQ&p#kQ&ockQ(Y`rTF=`!9iYG!!VQd!9aC_roa@_!;PdW!"\8n!9aC_
|
||||
ki`!Hki`!HkihpEqrmnW#j;6gki`!HkihsF"mG.M!9iYG!!MKc!9iYF!!VTM!!)6H
|
||||
qu?i_kPtV^kQ(Y`r9+.]!<)*`!!)6HrW!2e!!)3_!9iYE!<23\!9!&Cgb>t9p@&4R
|
||||
@'D?OrTF7,r9+AR4<kaj2IB/UkQ&ohkQ(Y`_<:k!jlc^F!.sD<kigeUnaY)tr;cZ_
|
||||
"RkX90^Sc%!7(6#!7$2[TBHC40WeaVn-&3^XYB,?kQ&p+kQaL<,8qjd?VLC]!7'im
|
||||
!!)u]!<<,9kPtVEkQ(Y`K'3C%khIl]nAju#mci^bm/?,JcLg<#c@Y8PkQBToX/bm^
|
||||
"R]!a0^Sc%!7(N+#=L[!)C7:K9`4)ScKOKi!2J`Y!!%W7"6et(0ZEJ`mH<F^mJZ5K
|
||||
cLg<#c@Y8PkQBToW(m!S"RW.f0^\i&!7(N+#=L[!)C7:K9`4)Sc@Y83kQ9u'0ZE;[
|
||||
kMb2MmJZ5KcLg<#c@Y8PkQBToW2TFT"QrLX0^\i&!7(N+#=L[!)C7:K9`4)Sc@Y83
|
||||
kQ^8,5fDO8h9+RXh:pPm5k"[8!7(6#!7$2[TBHsE5c@DU9rLdb9rLdb9rLdbW'KhM
|
||||
kQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$hgT:?a3Xt8[:Y'_rTF7,o]Q;#K'8ij"5ePt
|
||||
G4^Lj7t^F3kQ&p+kQaL<,8qjd?VLC]!7$2[K'3@$jQM_!`\7K[K_"d6kQ&p#kQ&n[
|
||||
kb%&@jQM_!oe6J5K_"d6kQ&p+kQaL<,8qje?VLC]!7$2[K'3C%kj7g1o]>c.q#9pg
|
||||
p@e1FrTF7,o]Q;#K'8fi"75OKo_eC]q#9pgp@e1FrTF7,r9+AR4<b[i2d]8VkQ&n[
|
||||
k^r$/kQ&p#kQ&n[k_J@%cMZl26p)Y3,r]1)r9+.+K'7gM\`a%>o]Q;#K'8!R!71T,
|
||||
#=LZu)C7=L9`4)Tcd7:-K'9i1!R]6ckQ0#VK'8'T!R]6kkQaL<+rVad?VL@\!RB&D
|
||||
k^r$3kQ0)Vo&p,"d":J>kQ0)Vqre8Q4<b[i2d]8Tk^q*3cFhF&cg^.McAKmIchci1
|
||||
6p)Y3,r]1)K'7gMK'7gMUZ_qN4<b[i2d]71k^r#Mk^r#nkQaL<+rVad?VH(8K'7gM
|
||||
K'8un#=LZu)C7=L9S2J[k^r#MkbI>H6p)Y3,r]1)K'7gMK'7gMUZ_qN4<b[i2d]71
|
||||
k^r#Mk^r#nkQaL<+rVac?VH(8K'7gMK'8un#=L[!)C7:K9S2J[k^r#MkbI>H6p)\4
|
||||
,rT+(K'7gMK'7gMUZ_qN4<kaj2IB.0k^r#Mk^r#nkQaL<,8qjd?VLC]JsV(U\!M^1
|
||||
K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IqYpd!q!ctH
|
||||
aRk)aK)`mk!1/<$K';dh#=L[!)C7:K9`4)SQi$dhrpAIln&MTRnc".?K)`sm!1/<$
|
||||
K';dh#=L[!)C7:K9`4)SQi$diq;BrLnB%i@b3o7\s+:9nrrAC;k^r$hkQaL<,8qjd
|
||||
?VLC]!13T_$N8oDeaLP]Zan``K)^H&b5VI.K'7gMo&p<H4<kaj2IB/UkQ$tGrsI]G
|
||||
g[N._ZEqEgon*3qs3(EBQ\+FQkjmpB6p)\4,rT+(r9+-IqYpu_oC)=l\&-G3ZHhq;
|
||||
qZ$Npp\t6o!.t6&s5X+ZQ\+FQkjmpB6p)\4,r]1)r9+-Iqu7-!iVNEEd`KAF`Nutt
|
||||
meZt_!.t6&s4@8NQ\+FQkjmpB6p)Y3,r]1)r9+-IrVmE%mHEL)qXi"OZEq3NZa\'R
|
||||
rt,52rr<'!rr<'!rr<'!!!*'!r;_HLK)b*8!1/<$K';dh#=LZu)C7=L9`4)SQi6pp
|
||||
gX4<rqYK`q\uiHR[Bm3Cqu79/!<3$!s8N'!s8N'!rr<'!!!%WNK)b!5!1/<$K';dh
|
||||
#=LZu)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*Lqu6d!!<3$!rr;os"TSK%!<;ut
|
||||
K)^H&kl1XLmHB/IPg09Tp#lWK4<b[i2d]8VkQ$tJrt!#Q[Cc%umC0F2]!o#PZ-<.G
|
||||
q>^Qrs8;p$s8N'!s8W#tK)^H&l2LaMmcX\sd":JHkQ0)Vp?2`L4<b[i2d]8VkQ$tJ
|
||||
rt!J_ZF/9"k-qY#Wi3),ZJGHY!<<-!rrE*"rr3!!!<3!!!!)ut!<<+Os+::8rrADS
|
||||
kQ0#VK'8E^!R]6fkQaL<+rVad?VLC]!13Za&)=Cp['5AA^:^:pI$U\@kPY>\!!*#u
|
||||
!<<-!rrE*"rr3$"!<;utK)^H&kl1XLn)sbsrTF=DhV7,FkLKRc"5DVfjS\4pQi-(-
|
||||
VZ?bqkQ&s'kQaL<+rVad?VLC]!13Za&(I\m^nl51guG2R?YG(pl%8qes3:QDQga,<
|
||||
cMcr/hVaDea=m]]J)fPdkQ$s(rrAD`kQ%OBD?92*rTF7,pZMiM4<b[i2d]8VkQ$tJ
|
||||
rstZuh;PV\htlr+F]`<fG0Y^>K)a*q!130<!7(Q,"5JoZbfKedgi\Y<r9+-ILAq7?
|
||||
r9+0ZDWh$$aR9*,kQ&p&kQaL<+rVad?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*
|
||||
s3:QDQga,<cMcr.ge5i2rW<&@9DdoQQ\PM?Qi-%JVf(_u"3AROs8D-]cM-N-6p)Y3
|
||||
,r]1)r9+-IrVmD#HZYIGDm$9m?"&/%M2fu9s+:9qrrADSkQ&p,kQ0Elrqsn8"8_XD
|
||||
lhorHQeDB=!3cD&Qi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<+rVad?VLC]!1/<;K)`C]
|
||||
!130<!7(Q,!o,L+a8#i0mP+#*kQ$tIs8;rbs8;rorr<&&rrAD`kQ@`#s8VBJ"3ARO
|
||||
s8D-]cM-N-6p)\4,r]1)r9+-IqYpd!q!ctHaRk)aK)`mk!130<!7(Q,!SfBLpB:3[
|
||||
l7hT&kQ$tJrr<&arr<&mrr<&&rrAD`kQ@`#s8VBJ"3AROs8D-]cM-N-6p)\4,r]1)
|
||||
r9+-Iqu7!%mG$7]a0*STrdt0%s2k9@Qga,<cMcr-gb@@Q!<<,to`5$mqXk!`n)uIl
|
||||
r9+-Irr2ruqZ$Nprr;rt!WW3!!!<3#!;c`p!!N?%!<<)u!4;b+Qi-%LVf)P7roj=\
|
||||
#NUn=/MTtVhu3TRkQAoImf37L!7(?&#=L[!)C7=L9`4)SQi$diq;BrLnB%i@b3o7\
|
||||
s+:9nrrADSkQ&p,kQ0HmiV!0MqXjjh!;uKj!!)lg"SD0H0^S`$!13]b!!)or!!*#u
|
||||
!W`6#q>UKrrrDrr!!*#u!W`6#r;Q`s[Jp5nr9+6\DZBb9kR[^nqN!6aDO6T53%9UX
|
||||
s8W&]"3AROs8D-]cM-N-6p)\4,r]1)r9+-Iqu7$%i8iGWa0)bZf_C'uK)a!n!130<
|
||||
!7(Q,!o,L&n+6V\!;?'a!;c<g!!)rh!<<,roE=dRk:l9#kQ$tKrr<&rrr<&urrN3#
|
||||
!;ulq!!3*"qu6Wrrr3*$rrE*!r;a8*!13WI"/g&:s8M3cs8?a^K(Am?"o4W@?Ma^#
|
||||
kQAoImf37L!7(?&#=L[!)C7=L9`4)SQhp^hi8r__`2p8N_T2>$s+:9orrADSkQ&p,
|
||||
kQBToo^qSC!<<,qo)o$no)JdioDARhoCMk[qXXj\mH-+hr9+-Irr2ruqu6Wrrr3$"
|
||||
rrE#t!!*#u!W`6#qu6Wrrr3*$rrE'!rr2ru[Jp5nr9+6\DZBb9kQLpF-S)_'rr^4p
|
||||
JcG]4"3AROs8D-]cM-N-6p)\4,r]1)r9+-IqYpu_oC)=l\&-G3ZHhq;r;Qct!<3!!
|
||||
!!)Zk!<<+Os+::7rrADSkQ&p,kQBTooCM>>!<<,sne2!'nc/[\nc/[\nc/[\!!)T\
|
||||
!!)ld"S(j?0^S`$!13Za!!)rs!!*#u!W`6#rVlitrr3'#s8N)srr<&urr`?%!<3&u
|
||||
rr<&,rrAD`kQ@`#s8W)^"l_(c9e<aLrrT,Je,AJ4aN3fLrTF7,pZMiM4<kaj2d]8V
|
||||
kQ$tHrse\\qYKp6ahl$9ZaJ*Hr;Qct!<3!!!!)Zk!<<+Os+::7rrADSkQ&p,kQBTo
|
||||
oCMkMr;Zigr;cZa!!)rf'*&%'!!)T\!!)T\!!)Qi!:o[\!;c6hna,?km/6&IQi-m^
|
||||
!!3-"rW)rtrW!!!s8;rss8;ous8W&u"TSK%s8W#t[Jp5nr9+6\DZBb9kQZl!o^5L*
|
||||
[/9k)rC225kQAoImf37L!7(?&#=L[!)C7=L9`4)SQi6ppp?h)%qYKj.`j2q`['R6`
|
||||
r;Qct!<3!#!!*'!r;['%rr<'!!<;ut!<;rsK)^H&nG`KTn)sbsrTF@=0_4f$nGrUi
|
||||
r:0U`%IjDunaQSZnGiRZnGiRcnHA@Ij=orukQ$s(rrAD`kQ@`#s8W)^#?>F:s6ic7
|
||||
Zhsb'K0]D!"3AROs8D-]cM-N-6p)\4,r]1)r9+-IrVmD_dE^8<qXM81XgbpMZa6k5
|
||||
s7u^#rr<'!rr<'!r;Zp!!!)or!<<+Os+::?rrADSkQ&p,kQBTonaZ&:!<<,rn,WLh
|
||||
rpUEu!:TsgnF-DXn,NIXn,NIbn-&4Fj"TitkQ$s(rrAD`kQ@`#s8W)^!A]E/rr_^e
|
||||
/$]$P!Mq=FkQAoImf37L!7(?&#=L[!)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*L
|
||||
r;Qct!<3!"!!*&r!!<0#!<3!!!!)rs!<<+Os+::>rrADSkQ&p,kQBTonaZ,<!<<,p
|
||||
n,WLhrpU!i!:]LU!!2TYquHT_"RkX90^S`$!1/H?!13WI"/g&:s8M3_0S03&"7T2<
|
||||
YPnJ%UFQ6+"3AROs8D-]cM-N-6p)\4,r]1)r9+-IrVmDGZF.=9md7Ki\%9&TZa%aP
|
||||
rrE*"rr3*$!<3$!r;Qct!<3!!!!)ut!<<+Os+::=rrADSkQ&p,kQBTonF4Qg"RbO6
|
||||
0^S`$!1/H?!13WI"/g&:s8M3_94e&$"7T8>Y5\G%LHb\#"3AROs8D-]cM-N-6p)\4
|
||||
,r]1)r9+-IrVmDTZa.!i_</54Yc=Y)Za/EbrrE*"rr3*$!<3$!r;Qct!<3!!!!*#u
|
||||
!<<+Os+::<rrADSkQ&p,kQ0Hma6s/ukM\,^r9+-ILAq7?r9+6\DZBb9kQ6Mon,31j
|
||||
nPq'?s8>K3rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13Za&)=Cp['5AA^:^:pI$U\@
|
||||
kPY>\!!*#u!rr?$s82iurr<&ts8Duus82kKs+::?rrADSkQ&p,kQ0Hma6EfjiS6-S
|
||||
r9+-Irr;osmf*7err;osW;cjar9+6\DZBb9kQ9KgLAUuTnl@3>V^TaekQAoImf37L
|
||||
!7(?&#=L[!)C7=L9`4)SQi6ppe?$9tV0:\Mj.pj*BS3JPK)^H&c2Rd1n)sbsrTFF@
|
||||
5fDO8h9=^Zh:pPm5k"X7!13]b!!*#u!!)Bc!!&hp!13WI"/g&:s8M3as+)].qu6ik
|
||||
=",kGs8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$tJrstZuh;PV\htlr+F]`<fG0Y^>
|
||||
K)a*q!130<!7(Q,"5eQAX3&]kca@A;oDIePQi@!b!<3!"!<<)u!!3-"r;cisrW!'#
|
||||
!<3&qs8E##rrAD`kQ@`#s8W)^"onF).ZjK)rrr7\-WBd>rTF@)aR9*,kQ&p&kQaL<
|
||||
,8qje?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*s3:QDQga,<cMcr/jQM_!a=m]]
|
||||
K_"d5kQ$tKrr<&urrN3#!<3!"!<3&urrN3#!<)p!!<3&rrr<&urr<&%rrAD`kQ@`#
|
||||
s8W)^&-)\'I474"PEU5R.!G7_s8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$tJrst`K
|
||||
FH`G;Y-3:[@=<0QNRNLZK)a*q!130<!7(N+"75OKo]Gi0q#9pgp@e1Fr9+-Irr;os
|
||||
!WW2t!!3*"rr3'#rr<&urrN3#!;lcr!<2uu!3Z>%Qi-%LVf)P7roj=\#Ln2d.k3`*
|
||||
d/F"CkQAoImf37L!7(?&#=L[!)C7=L9`4)SQ\,6hs1/.0Qga,<cF<!;Qi@!b!;uis
|
||||
!;uis!<2uu!<3!%!!*$!rrDrr!!*#u!!'2%!13WI"/g&:s6AeMaN3fLrTF7,pZMiM
|
||||
4<kaj2d]8VkQ$tGrs&JtnCb=moRd*ps2Y->Qga,<cF<!;Qi@!b!;uis!<3!"!<3&u
|
||||
rr<&trriE&!<<'!r;Q`srr2ruY5\Kgr9+6\DZBb%kQAoImf37L!7(?&#=L[!)C7=L
|
||||
9`4)SQi$dhrpAIln&MTRnc".?K)`sm!130<!7&(;!13]b!!)orrW!!!s8;ous8W&u
|
||||
!rr9#rr;os!WW3!!3Q8$Qi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<,8qje?VLC]!13T_
|
||||
$MiW5bOEWV[E@q:K)^H&b5VI.n)sbs\**gYo)A[iQN$rOr9+3[DZAn@!Ug!dkQ&p&
|
||||
kQaL<,8qje?VLC]!13T_$N8oDeaLP]Zan``K)^H&b5VI.n)sbs\**gYo)A[iQN$rO
|
||||
r9+0ZDW]"@mf37L!7(?&#=L[!)C7=L9`4)SQhp^hi8r__`2p8N_T2>srrE*"K)^H&
|
||||
rVlkan)sbsrTF=DhV7,FkLKRc"5DVfjS\3AQ\PM?Qi-%IVr[7Gs8D-]cM-N-6p)\4
|
||||
,r]1)r9+-IqYpu_oC)=l\&-G3ZHhq;qu?Qoli6k_q>UHq!.t6&s8DrtQga,<cMcr/
|
||||
hVaDea=m]]J)fPdkQ$s(rrAD`ki2X@kQ&p&kQaL<,8qje?VLC]!13T_%JJcWqY&@Z
|
||||
_SsL#[Ee4<rrE*"kl1Y`!;6?m!!%WNK)bfL!130<!7(Q,"5JoZbfKedgi\Y<r9+-I
|
||||
LAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt"hjkhu=6oZY=\Zb3ZO\&nRJ!<<,ss8;rs
|
||||
s8;ous8W#t"98B$!;lfp!!WE&!!*'!r;_HLK`;%=n)sbsrTF=<9?YBT!r^87qre$H
|
||||
LAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt!l3cID^en\)N9\%B&SZ`j<,!<<,trs/T)
|
||||
s8N'!rr<&prr`<%rr<&srs/T)s8N'!rr<&srrE*"K)^Q)!130<!7(Q,!S]=-r5ng<
|
||||
qXcK-r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrsuoW\&%q;n@?!6\[]#QZap#6
|
||||
!<<,trs/T)s8N'!rr<&ss82iurr<&srsA`+s8N'!rr<'!s82kKs+UIQQga,<cMcr.
|
||||
gbATFq#g9W0^S`$!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQi6pp_m6\^oBu"TZa[NT
|
||||
Za6p\r;Qct!;uj&!!*'!!!*$!!<)p'!!*'!!!*$!!;uj-!!*'!!!*$!!<3$!s8N'!
|
||||
K)^Q)!130<!7(Q,!SfBLpB:3[l7hT&kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13Za
|
||||
&(%Yg[FW1V\$E6<W33J4h>I9R!!)rs#QOl)rr<'!!!)ut#QOl)rr<'!!!)rs%fcV0
|
||||
rr<'!!!*$!!<<'!!.t6)rrADSkQ&p,kQ0Hmde*V@!;Q3io^Cutm/6&IQ\PM?QeCR&
|
||||
cM-N-6p)\4,r]1)r9+-IrVmD`Yd1X?Lto_WV1X/]Vn)!fs82its8W#trr;os!WW2t
|
||||
!!3-"qu?cts8;p$s8N'!s8VusK)^Q)!130<!7(Q,!SfBfp&"gao`5$mq"4d^n)uIl
|
||||
r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tJrt!V\]>17dh;%%dG$ep8Y3CQ<K)a*q
|
||||
!130<!7(Q,!o,L&o(2q_!;#gd!!)Z`!!)fd!<<,poE=dRk:l9#kQ$s(rrAD=kQ&p&
|
||||
kQaL<,8qje?VLC]!13Za&"TWSiN[L^qX]ek=D25gc@Z(Js3:QDQga,<cMcr/gbABm
|
||||
p%&1a!:fX]!!*#i!rr>moDJXkoCDq^q""XZmH-+hr9+-ILAq7?g#rF]pZMiM4<kaj
|
||||
2d]8VkQ$tJrssRXipO-seFVLW@o$B9<N^rRK)a*q!130<!7(Q,"5GU%oCqeV!!)KY
|
||||
!<<-!nd>Etnc/[\nc/[\!!)fb"S(j?0^S`$!1/H?!12C&!7(?&#=L[!)C7=L9`4)S
|
||||
Qi6ppT6k[DU2R3<IU-B1Ef#e)K)^H&c2Rd1n)sbsrTF@=0_=o2nc/[do)/Ogo)/Re
|
||||
nc8^jrpg*j!:p!e!qH<kq!nRXm,]qfr9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$s$
|
||||
s+:9]rrADSkQ&p,kQBToo()PF!<<,gnGrUirp^*k!:^$hr:'df!;Q'enE]-hm/6&I
|
||||
Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMh!p:/=PBK)^H&ec,W9n)sbsrTF@=0_+]+
|
||||
n,WLhnaHhb!:]IX!:]IX!;u<e!!)f`"RkX90^S`$!1/H?!12C&!7(?&#=L[!)C7=L
|
||||
9`4)SQg4SR/2K(23.h0^s4.,LQga,<cMcr/gbA9goC)b\!;#^X!<)Eb!!;Wi!;Q$d
|
||||
n*8pem/6&IQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMh,A2)Qj=Mi*CJK)^H&g&D&=
|
||||
n)sbsrTF@=0_"SRmf`(Ci\9`skQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%kTXr
|
||||
.:.^^F)(aTpo('eUk8Vus5<nWQga,<cMcr-gb?e;"RYC20^\f%!1/H?!12C&!7(?&
|
||||
#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U<C]FBg^qd:0K)^H&i;WeDn)sbsrTF:;0ZWG]
|
||||
kMb2MmJQ/JQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XB
|
||||
s8E#prr<&_rr<%Ns,6mWQga,<cMcr1h*Ap8h;-<3"l7qb\j5`^kQ$s(rrAD=kQ&p&
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr/hV!;ZWp!9jF_!.t6/rrADS
|
||||
kQ&p,kQB^kBrfA&"OFJfKCf$)!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
|
||||
Kp%U<C]F.Fj5[D)qu6]ts8W#t!WW3!!!WB&rrE*!rW!!!s8;rss8E!!s8W&uK)^i1
|
||||
!130<!7(Q,"6A[.9?8dh5_S_#r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=
|
||||
2(+*@P&OiVGJW>"Z&\_]!s&B$!<3!"!<3&urrE*"qu6]trrE&u!W`6#rr3$"rr@ZN
|
||||
MuNdDn)sbsr9+7LnFQ;7p#l,Lo`Op]p$;P>!1/H?!12C&!7(?&#=L[!)C7=L9`4)S
|
||||
Qg4S]/N#C5Kp%U*A7oGjj5[D)qu6`us8N)urrN3#!<2uu!<)rr!!3*"rr3!!s82it
|
||||
rr@ZNMuNdDn)sbs\**gYLAq7?g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJ
|
||||
B>W]hZ&\_]!s&B$!<3!"!<3&urr<&urr<&urrN3#!<3!"!<3&srr<%Ns,6mWQga,<
|
||||
cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XArrW9$
|
||||
rrE&u!W`6#rr2rurr2rurr3$"rrE&u!W`6#rr3$"rr@ZNMuNdDn)sbs\**gYLAq7?
|
||||
g#rF]pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\b^rW!!!!<3!&!<<'!
|
||||
!<3&ts8;ourrE&u!W`9#rW)rt!<<+Os,I$YQga,<cF<!;Q\PM?QeCR&cM-N-6p)\4
|
||||
,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=Vrs+::/rrADSkQ&o;kQ$s(rrAD=kQ&p&
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt_W0[]Ne7:_s5<nWQga,<cF<!;Q\PM?
|
||||
QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=Jns+::/rrADSkQ&o;
|
||||
kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%nfYm:ipu.AnPafOe88&m"57hs5<nW
|
||||
Qga,<cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IK)^H&\c2Yrn)sbs\**gYLAq7?
|
||||
g#rF]pZMiM4<kaj2d]8VkQ$t7rrf`):J<_=s3Tt]s-<TaQga,<cF<!;Q\PM?QeCR&
|
||||
cM-N-6p)\4,r]1)r9+-IlMgu<1G^I>oDd2$K)_,9!130<!7&(;!1/H?!12C&!7(?&
|
||||
#=L[!)C7=L9`4)SQg4SV/N#C815h$IM"gqrk^ri"rrADSkQ&o;k_,;UkQ&p&kQaL<
|
||||
,8qje?VLC]!13!N%kTXr.:.^^F)(aTpo('eV#LD@k^ri"rrADSkQ&n[k`P'/cM-N-
|
||||
6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s8Ibg^pA^ns3Tt]s-<TaQga,<c@Y8BkQ&s'
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\NrK%ZkihpEqWInZki`!Hq<3G1
|
||||
Q2^iNn)seud":JFkQ0)WpZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P&P4:pVGnMZ&\h`
|
||||
!pJhJp?2JVki`!Hq<3G1Q2^iNmcX\sd":JHkQ0)Vp?2`L4<kaj2d]8VkQ$t7rsp\=
|
||||
2(+*@P&P4:pVGnMZ&\h`!pJhJr9++\roa@_kl(PckQ'fHkii!G!U/bG!<23]!!2<I
|
||||
rW)iZK)_,9!13*:K$KV+!71?%#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U<@=*47j5[D)
|
||||
rr3#_kktM\kQLtM!9iVHroa@_!;ks]!9aF^kQ1bJ!<20`!9aFYk^ri"rrAC;k^r$h
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_H?=[\Z_rKd^NrK%[ki`$CkPtV^kPtV^kPtV]
|
||||
kktJ^kQ(VG!<D?]!!29`q<3G1Q2^iNK'7gMo&p<H4<kaj2d]8VkQ$t7rsp\=2(+*@
|
||||
P%ncJB>W]hZ&\h`!pJhJqWInZroa=^roa=^roa=^roaC`kQ(VG!W_Ear9++\q<3G1
|
||||
Q2^iNK'7gMo&p<H4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\h`!pJhJqre1`
|
||||
kQ'i1!<20^!<20^!<20`!9aF^kQ1bJ!<20`!9aFYk^ri"rrAC;k^r$hkQaL<,8qje
|
||||
?VLC]!13!N%kTXr-\[_HC27Tt_W0[]NrK%ZkihpE!U'O_kQV%NkPtVH!<)-[!!29`
|
||||
roaC`kii!Groa@_!;ku3s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0Qq
|
||||
CM1NEj0=XDs3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NE
|
||||
j0=XDs3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=L@
|
||||
s3Tt]s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IlMhAf:/4W-H$O"7B4[3tT8Dq6s3Tt]
|
||||
s-<TaQ\+FQkjmpB6p)\4,r]1)r9+-IfDj4]K)_,9!1/<$K';dh#=L[!)C7=L9`4)S
|
||||
Qg4SR[8'Lk2hM']s4.,LQ\+FQkjmpB6p)\4,r]1)r9+-IlMgu<1G^I>K)^H&ec,W9
|
||||
K'7gMo&p<H4<kaj2d]8VkQ$t7rs1262(CA>MMd4As+::(rrAC;k^r$hkQaL<,8qje
|
||||
?VLC]!13!N%kTXr.:.^^F)(aTpo('eUk8Vus5<nWQ\+FQkjmpB6p)\4,r]1)r9+-I
|
||||
lMhAH2)Qb8P*0d"s8Ibg^pA]Gs+::/rrAC;k^r$hkQaL<,8qje?VLC]!13!N%kTXr
|
||||
-\[_HE,5LJ_;jR\Nr8nW!<)ot!9X=[!.t6/rrAC;k^r$hkQaL<,8qje?VLC]!13!N
|
||||
%kTXr-\[_HE,5LJ_;jR\Nr8nW!<)ot!9X:]!<2uu!.t60rrADQk^q*Ec2c2`kQaL<
|
||||
,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr8nW!<)p!!<3&urrE-"rW!$"!!*#u
|
||||
rW!!!s8;p!s8N)urr<&us8E#ts8E!!s8W&u!rr9#rr30&rrE'!s8W&u!WW3!!<3#t
|
||||
!.t6\rrADRkQ/uUK'8K`!R]3dkQaL<,8qje?VLC]!13!N%kTXr-\[_HE++*;_;jR\
|
||||
Nr8qS!!3*"rr36(rrE*!!<<'!r;QfurrE&u!W`6#rr3'#s8N)urrN3#!<)ot!<3!"
|
||||
!<3&urrrK'!!*'!!<)ot!<3!"!<3%Ns0_k,Qga,=cd7:-PNW%pchHW.6p)\4,r]1)
|
||||
r9+-IlMhAH2)Qb8P*0-^B4Sp?j0=XBrr<&trrN3#!<3!*!<3'!rrE*!!<<)t!!3*"
|
||||
rr3!!s8;rss82iurr<&urr<&urrN3#!<3!"!<3&urr<&ts82iurr<%Ns0hq-Qga,<
|
||||
cMcr.jPJYPg?7#cg&p*bhW4UuKU;W#j/2nWrTF7-pZMiM4<kaj2d]8VkQ$t7rsp\=
|
||||
2(+*@P%ncJB>W]hZ&\b^!!)ut!W`6#rr3<*rrE*!!<<'!rrE&u!W`6#rr3-%rrE*!
|
||||
!<2uu!;c]t!!*$!rr3$"rrE&u!W`6#rr2rurVlitqYpQr!.t6\rrADSkQ&p,kQB]"
|
||||
N_@GI"$h@rir&!?Q\PM?Qi-%IVr_dsmf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
|
||||
Kp%U6CMRS"j5[D)r;Q`srVlp!rrE&u$3:)+s8N*!rrE'!rr3$"rrE&u!W`6#rr3'#
|
||||
s8N)urr<&trrN3#!<3!"!<3&urrN3#!<2uu!<)ot!<2uu!<)ot!.t6\rrADSkQ&p,
|
||||
kQBV#Fj.r,"5J$ZjS\3AQ\PM?Qi-%JVf(\t!m'g0rTF7,pZMiM4<kaj2d]8VkQ$t7
|
||||
rsp\=2(+*@P%ncJB>W]hZ&\b^!!)ut!W`9#r;[0(!<<'!s8N*!s8;ourrE&u!W`6#
|
||||
rVlp!s8W&u!WW3!!<3#t!<3#s!!3*"rVuis!WW3!!!3-"rW%QM\,QGpn)sbsrTF=<
|
||||
9?YBT!r^87qre$HLAq7?r9+0ZDWq*&aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=
|
||||
2(+*@P%ncJB>W]hZ&XG9K)ad/!130<!7(Q,!S]=-r5ng<qXcK-r9+-Ig&D$PYQ"Th
|
||||
r9+6\DZBb%kQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D)
|
||||
K)^H&i;WeDn)sbsrTF=<0`&ic"8)"8m/6&IQi-m^!:Bgb!;c]q!;?Hj!;c]q!9jF_
|
||||
!9*qXQi-%LVf)P7lKA>kaR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt
|
||||
_W0[]MLtk[s5<nWQga,<cMcr-gb?eC"SVBN0^S`$!13Za!!)<a!!)`m!!)`m!!)`m
|
||||
!!)6_!!)!X!13WI"/g&:s6AeMaN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsqat:/H%X
|
||||
H"L]%AW`UWM<oioK)ad/!130<!7(Q,!SfB\o`5$mr:L'j!;c?ko^Cutm/6&IQi@!b
|
||||
!;c`p!<3#t!!3-"rW!$"rrDoqrW!*$rrE*!rW)iq!!)rs!!*#u!<E0!!!WB&rrE*!
|
||||
rW!!!s8;rss8E!!s8W&uj8T+Gr9+6\DZBb9kl(MdjGlnc0hmM^rVui["3AROs8D-]
|
||||
cM-N-6p)\4,r]1)r9+-IK)^H&\c2Yrn)sbsrTF:;0]D^(!;c?h!!)ri!<<,ro`XpU
|
||||
kV2B$kQ$tKrr<&rrr<&urrN3#!;ZWr!<3&rrr<&urrN3#!;uis!;ulq!<3!%!<3'!
|
||||
rrE&u!<<,srrN3#!<3!"!<3&urrN3#!9*qXQi-%LVf)P7roamms8%d/12`GCGrR7-
|
||||
q>^KnkQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4SR[8'Lk2tR('k^rhmrrADSkQ&p,
|
||||
kQ9Nnp$_MR!!)`brW)fe!<<,toDnplqXap^mcQ:jr9+-Irr2ruqu6Wrrr3$"rrDus
|
||||
r;Zlu!;lcr!<3!$!<3'!s8;rqrr<&qrr<&urr<&urr<&ts8;ourrE&u!<E/t!!3*"
|
||||
iVrnEr9+6\DZBb9kQV"bCaao+rVm&sRkJ+Es8D-`aN3fLrTF7,pZMiM4<kaj2d]8V
|
||||
kQ$t7rral/1FY<Ts4Z[gs,6mWQga,<cMcr/gbABmmdgGZ!;Z3h!!)Tj!<2Tf!!2]_
|
||||
quHTb"S1sB0^S`$!13]b!!)or!!*#u!W`6#rVlitrr3$"rrDrr!!*#u"9AH%rrE&u
|
||||
!!)rs!!)lq!!*#u!!*#u!!*#u!!*#u!W`6#rr3$"rrDus!!)!X!13WI"/g&:s8M3b
|
||||
s,ABV\GH4-`A)rDrTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N#V@nk.Pcp>MMV$,
|
||||
g?=.gMuNdDn)sbsrTF@=0_=o&nc8^jqskC#!:g*io'ub\o'ub\nc/[\nc/[dnc\LL
|
||||
jY6'!kQ$tJrr<&srr<&urrN3#!<)ot!<3!#!<<'!r;Q`srr3*$rrE'!rr30&s8N*!
|
||||
rrDrr"T\Q&s8N)urr<&urr<&urrN3#!<3!"!<3&urrN3#!9*qXQi-%LVf)P7roaOF
|
||||
/;$YJ[eg"*W%$3okQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C7?A4)SCB+>/
|
||||
W2?Gfrr:^9K)^c/!130<!7(Q,"5GU%oDA+W!!)Tg!;Z0c!;uC$!!)Qi!:o[\!:o[\
|
||||
!:g*io'ub\qXOdZm,]qfr9+-Ir;Z]q!WW3!!<3#t!!3-"r;cisr;Zlus8E!$s8N*!
|
||||
s8;p#s8N*!s82itrrE&u"p"]'!!*$!rVufr!WN0!rrN3#s8E#trrE*"j8T+Gr9+6\
|
||||
DZBb9kQZl!o^5L*[/9k)rC225kQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
|
||||
Kp%U<C]FBg^qd:0rr;$B!W_EaqriY3MuNdDn)sbsrTF@=0_4f$nGrUir:0U`%IjDu
|
||||
naQSZnGiRZnGiRcnHA@Ij=orukQ$s(rrAD`kQ@`#s8W)^#?>F:s6ic7Zhsb'K0]D!
|
||||
"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XDrrM?Ir;c*G
|
||||
!W_EaqriY3MuNdDn)sbsrTF@=0_+]$n,WLhqX=Lc!<2Hu!!)Kg!:]IX!:TsgnF-DX
|
||||
qX=XVlJjSbr9+-ILAq7?r9+6\DZBb9kQ*Gnrr3)h;(JpLrrJrHrTF@)aR9*,kQ&p&
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\NrK%[ki`$GkPtVJkQ1bJ!;ku3
|
||||
s,6mWQga,<cMcr/gbA9gnF-GY!;Q$a!!*#f!rr>jnGE7enF6>UqX=XVlJjSbr9+-I
|
||||
LAq7?r9+6\DZBb9kQ*AgrVluh;C\mKrrJlErTF@)aR9*,kQ&p&kQaL<,8qje?VLC]
|
||||
!13!N%kTXr-\[_HE,5LJ_;jR\NrK%[ki`$GkQ1bJkl(P`ki`$GkQV%N!9aFHkl(Pb
|
||||
ki`$1!;ku3s,6mWQga,<cMcr/gbA6eamTB#l/FD`r9+-ILAq7?r9+6\DZBb9kQ+=f
|
||||
r;Qlg<%>'MrrIm=rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HE++*;
|
||||
_;jR\NrK%[ki`$GkPtV\kQ1bJ!<20d!9aC_ki`$GkQCnL!9aF[k^rhmrrADSkQ&p,
|
||||
kQ0Hma6s/ukM\,^r9+-Ig&D$PgA_3SrrCaP!13WI"/g&:s8M3`LGA8qrs/'o.]i[K
|
||||
89Xsq"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0-^B4Sp?j0=XDrrM?I
|
||||
r;ci\r;[)dkQ'fHki`$GkPtV^kQCnL!9aF[k^rhmrrADSkQ&p,kQ0Hma6EfjiS6-S
|
||||
r9+-Ir;Z]qmJm+bqYpNqpAb'kl2LebrrCaP!13WI"/g&:s8M3`gF@sTrs&$p.B99o
|
||||
bPgW,aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\h`!pJhJ
|
||||
r9++\roaUfki`$1!9iVHroa=^roaIbkQ'fHqriY3MuNdDn)sbsrTFF@5fDO8h9=^Z
|
||||
h:pPm5k"X7!13Za!!)<a!!)`m!!)`m!!*#u!!)<a!W`6#g&D&=r9+6\DZBb9kQCj9
|
||||
/%,9S"nPeE0m*HokQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"
|
||||
j5[D)rr3&`kQ(PE!!*#^!!*#^!!*#^!!*#^!!*#^"9@WckQ(MDK)^c/!130<!7(Q,
|
||||
"5eQAX3&]kca@A;oDIePQi@!b!;c`p!<3#t!!3-"rW!$"rrDoqrW!*$rrE*!rW)iq
|
||||
!!*#u!W`9#rW!$"rrE&u"p"Z'rrE*!rW!*$rrE'!g&D&=r9+6\DZBb9kQV"_>q1s3
|
||||
rVm&tO=+!$s8D-`aN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJB>W]h
|
||||
Z&\h`!pJhJqrmtYroa=^roa=^rTO4\"R,%LkQ(MDK)^c/!130<!7(Q,"6A[.9?8dh
|
||||
5_S_#r9+-Irr2ruqu6Wrrr3$"rrDlp!W`6#qu6Wrrr3$"rrDus!!)rs!!*#u!!)rs
|
||||
!W`6#rr30&rr<'!rrE&u"9AH%rrCaP!13WI"/g&:s8M3ms8Ve@.6;U8PB]2<G4bh7
|
||||
rTF@)aR9*,kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_HC27Tt_W0[]NrK(LkPtVJ
|
||||
k^rhmrrADSkQ&p+kQC2@oCV2<kP5&L"8;H]lhorHQi@!b!;lcr!<3!"!<3&ss8;ou
|
||||
rrDrr!!*#u"9AH%s8W#tr;Z]qrr;os#QOf(rrE*!!<2uu!<3!$!<3'!!87APQi-%L
|
||||
Vf)P7roj=\#Ln2d.k3`*d/F"CkQAoImf37L!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5
|
||||
Kp%U6CMRS"j5[D)rr;QQ!!)<JK)^c/!130<!7&(;!13]b!!)or!!*#u!W`6#rVlit
|
||||
rr3$"rrDrr!!*#u"9AH%rrE&u!!)rs!!)rs!!*#u#QXo)!<3'!rrE&u!!*#u"9AH%
|
||||
rrCaP!13WI"/g&:s6AeMaN3fLrTF7,pZMiM4<kaj2d]8VkQ$t7rsp\=2(+*@P%ncJ
|
||||
B>W]hZ&8P\g?=.gMuNdDn)sbs\**gYrVlitr;Q`srr3$"rrE#t!!*#u!s&B$!;uis
|
||||
!<3!$!<3'!!<3!&!<<'!s8N)srr<&urr<&urr<&urr<&urr<&urr`?%!<3&PrrAD`
|
||||
kQ@`#s8VBJ"3AROs8D-]cM-N-6p)\4,r]1)r9+-IlMhAf:/4W-H$O"7B4[3tT8Dq6
|
||||
s4Z[gs,6mWQga,<cF<!;Qi-m^!!3-"rW)rtrW!!!s8;rss8;ous8W&u"TSK%s8W#t
|
||||
"onT&s8N)rs8;rsrr<&urr<&ts8E!$s8N*!!87APQi-%LVf)P7lKA>kaR9*,kQ&p&
|
||||
kQaL<,8qje?VLC]!12=;g?=.gMuNdDn)sbs\**gY_#FB7aSu7,r9+3[DZAn@!Ug!d
|
||||
kQ&p&kQaL<,8qje?VLC]!13Q^#6+Defso,qK)^H&a8Z.+n)sbs\**gY_#FB7aSu7,
|
||||
r9+0ZDW]"@mf37L!7(?&#=L[!)C7=L9`4)SQi$dhrpAIln&MTRnc".?K)`sm!130<
|
||||
!7(Q,!p&4mjP&eIrn7J/gtq,ikQ$s(rrAD`kQ%OAmK!:ckQ&p&kQaL<,8qje?VLC]
|
||||
!13T_$MiW5bOEWV[E@q:K)^H&b5VI.n)sbsrTF@?i/UIO0EXRij5U"#!1/H?!13WI
|
||||
irAu@!7(?&#=L[!)C7=L9`4)SQi$dirSZben&MT;\_-\/s+:9nrrADSkQ&p,kQBV#
|
||||
Fj.r,"5J$ZjS\3AQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IqYpo\jkK:CXKo1La7Y&a
|
||||
K)a$o!130<!7(Q,!o-Gla8Q/=b"MWq!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQhp^j
|
||||
iUcO1a1&q2aKj+[rVZ]n!:0Xe!!*'!quD?KK)bQE!130<!7(Q,!S]=-r5ng<qXcK-
|
||||
r9+-ILAq7?g#rF]pZMiM4<kaj2d]8VkQ$tHrse\\qYKp6ahl$9ZaJ*Hr;Qp#!<<'!
|
||||
!9sLa!!%WNK)bEA!130<!7(Q,!o,L+a8#i0mP+#*kQ$s(rrAD=kQ&p&kQaL<,8qje
|
||||
?VLC]!13Za&,,DSi;3<Bbf6rp]X5#Sao)/D!!*'!!!*'!r;Zlus82lrs8;p$rr<'!
|
||||
!!)orr;_HLK)bcK!130<!7(Q,!SfBLpB:3[l7hT&kQ$s(rrAD=kQ&p&kQaL<,8qje
|
||||
?VLC]!13Za&)5LWeGB%3]t1>T]="uOYPeD9!!*'!!!*$!!<<'!!<3$!s8N'!rr<&t
|
||||
rr`<%rr<&srriB&s8N'!K)^H&rVlkan)sbsrTF:;0[fUp!!)fe"SD0H0^S`$!1/H?
|
||||
!12C&!7(?&#=L[!)C7=L9`4)SQi6pp^q7(lqYK]l[^3NS['R*Lr;ZZp!WW2s!!iN(
|
||||
!<<'!!<;ut#64]'!<3$!r;Qp#!<<'!!.t6&s8DrtQga,<cMcr-gb@^[quHKa!<<,p
|
||||
o`XpUkV2B$kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13Za&&Y]\]CYIX\$NQT\$NEG
|
||||
bl%JA!!)rs!<<,trs&N(s8N'!s8W#t"oeQ&rr<&srriB&s8N'!K)^H&rVlkan)sbs
|
||||
rTF=<0_P#/!<<,koE>3po^i+`q"+Re!;Q0hoBtcqm/6&IQ\PM?QeCR&cM-N-6p)Y3
|
||||
,r]1)r9+-IrVmDTZa.!i_</54Yc=Y)Za/EbrrE*"r;Qct!;uj#!!*'!!!)ut#64c(
|
||||
!!*$!!;uj#!!*'!!!%WNK)bfL!130<!7(Q,"5GU&o_%eV!!)Q\!<<-!o)esmoCMn\
|
||||
"7u*a!;Q-go'PQnm/6&IQ\PM?QeCR&cM-N-6p)Y3,r]1)r9+-IrVmD`Yd1X?Lto_W
|
||||
V1X/]Vn)!grrE*"qu?Qo!<;rs!WW2u!!WE&!!*'!qu?cts8;qLs+::KrrADSkQ&p,
|
||||
kQBTooCM_I!<<,gnc8^jrpgEs!:g*io'ub\nc/[bnc\LLjY6'!kQ$s(rrAD=kQ&p&
|
||||
kQaL<+rVad?VLC]!13Za&(I\m^nl51guG2R?YG(pl0eQP!!%WNK)aj1!130<!7(Q,
|
||||
"5GU%oD%kV!;c9b!!)Tg!<)Hh!!*#h!WW5kqZ$]g!!)fb"S(j?0^S`$!1/H?!12C&
|
||||
!7(?&#=LZu)C7=L9`4)SQi6ppSYt<&Z#nn"o8n)sBOl;3mf*:f!.t6&s5O%YQga,<
|
||||
cMcr/gbA<ip[J7a!:TFY!!*#g"98Gl!!)re!<<,pnHA@Ij=orukQ$s(rrAD=kQ&p&
|
||||
kQaL<+rVad?VLC]!13Za%t:M;m^%,eoA,I;:L.7+Y(H\*s3:QDQga,<cMcr/gbA9g
|
||||
p$_t^!:fOb!!)NX!!)NX!!)rd!<<,pn-&4Fj"TitkQ$s(rrAD=kQ&p&kQaL<+rVad
|
||||
?VLC]!13Za&"e2jPG2uuYC9bcI<(1(dt7UOs3:QDQga,<cMcr/gbA9goC)b\!;#^X
|
||||
!<)Eb!!;Wi!;Q$dn*8pem/6&IQ\PM?QeCR&cM-N-6p)Y3,r]1)r9+-IK)^H&\c2Yr
|
||||
n)sbsrTF@=0_"SRmf`(Ci\9`skQ$s(rrAD=kQ&p&kQaL<+rVad?VLC]!13!N"LV!#
|
||||
9K.S'K)aC$!130<!7(Q,!SfBLmf`%@i@sZskQ$s(rrAD=kQ&p&kQaL<+rVad?VLC]
|
||||
!13!N"=u>b.6)qZK)aC$!130<!7(Q,!SfBLl3-;/gbA-nkQ$s(rrAD=kQ&p&kQaL<
|
||||
+rVad?VLC]!13!N#V@nk.Pcp>MMQlaK)aO(!130<!7(Q,"l2G^hVI#3h?D`if=F69
|
||||
r9+-ILAq7?g#rF]pZMiM4<b[i2d]8VkQ$t7rsp\=2(;jcKl_#/s7iOiVPJhDK)ad/
|
||||
!130<!7(Q,"5eQAX3&]kca@A;oDIePQ\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH
|
||||
2)Qb8P*0d"s8Ibg^pA]Gs+::/rrADSkQ&p,kQBo0O\<bL"$hP1o_dnQQ\PM?QeCR&
|
||||
cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0d"s7a@ij0=XBs8E#prr<&_rr<%Ns,6mW
|
||||
Qga,<cMZl.m-sW=k4Rp4rq-Bep@[bLkQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N
|
||||
%kTXr-\[_HE,5LJ_;jR\Nr/hV!;ZWp!9jF_!.t6/rrADSkQ&o;kQ$s(rrAD=kQ&p&
|
||||
kQaL<,8qje?VLC]!13!N%kTXr-\[_HE,5LJ_;jR\Nr/hX!<<)t!!3-"rW!-%!<3'!
|
||||
s8E!!s8W#trr;rt!WW3!!.t61rrADSkQ&o;kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]
|
||||
!13!N%kTXr-\[_HE++*;_;jR\Nr/hY!<<'!rr3$"rrE&u!<<,srrN3#!<3!"!<3&u
|
||||
rrN3#!.t6/rrADSkQ&o;kQ$s(rrAD=kQ&p&kQaL<,8qje?VLC]!13!N%kTXr-\[_H
|
||||
?=[\Z_rKd^Nr/hY!<<'!rr3$"rrE&u!!)utr;Zlu!<3!!!<;rs!WN.Os,6mWQga,<
|
||||
cF<!;Q\PM?QeCR&cM-N-6p)\4,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XArrW9$
|
||||
rrE&u!W`6#rr2rurr2rurr3$"rrE&u!W`6#r;Q`sK)^c/!130<!7&(;!1/H?!12C&
|
||||
!7(?&#=L[!)C7=L9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D)qu6`us8N)urrN3#!<2uu
|
||||
!<2uu!<3!"!<3&urrN3#!<3!"!<3%Ns,6mWQga,<cF<!;Q\PM?QeCR&cM-N-6p)\4
|
||||
,r]1)r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XBs8E!!rrE&u"p"]'!!*$!rVufr!WN0!
|
||||
rrN3#s8E#trrE*"K)^i1!130<!7&(;!1/H?!12C&!7(?&#=L[!)C7=L9`4)SQg4S]
|
||||
/N#C5Kp%U6CMRS"j5[D)K)^H&i;WeDn)sbs\**gYLAq7?g#rF]pZMiM4<kaj2d]8V
|
||||
kQ$t7rsp\=2(+*@P%ncJB>W]hZ&XG9K)ad/!130<!7&(;!1/H?!12C&!7(?&#=L[!
|
||||
)C7:K9`4)SQg4S]/N#C5Kp%U6CMRS"j5[D%K)^H&i;WeDn)sbs\**gYLAq7?g#rF]
|
||||
pZMiM4<kaj2IB/UkQ$t7rsqat:/H%XH"L]%AW`UWM<oioK)ad/!130<!7&(;!1/H?
|
||||
!12C&!7(?&#=L[!)C7:K9`4)SQ\,6hs1/.0Qga,<cF<"jQeCR&cM-N-6p)\4,rT+(
|
||||
r9+-IlMh!p:/=PBK)^H&ec,W9n)sbsK'8?\!7(?&#=L[!)C7:K9`4)SQg4SR/2K(2
|
||||
3.h0^s4.,LQga,<c@Y8BkQ&s'kQaL<,8qjd?VLC]!13!N#V@nk.Pcp>MMQlaK)aO(
|
||||
!130<!RK,Ek`b32dEhRN#=L[!)C7:K9`4)SQg4S]/N#C7?A4)SCB+>/W2?GfK)^H&
|
||||
i;WeDmcX\sd":JHkQ0)Vp?2`L4<kaj2IB/UkQ$t7rsp\=2(+*@P&P4:reA5(Z\3r1
|
||||
K)ad/!13*:K$KV+!71?%#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.Fj5[D)r;ZZp
|
||||
qYpNqkl1V_K)^i1!1/<$K';dh#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.Fj5[D)
|
||||
r;Q`spAY*mkl1V_K)^i1!1/<$K';dh#=L[!)C7:K9`4)SQg4S]/N#C5Kp%U<C]F.F
|
||||
j5[D)r;Q`sr;Q`srr3!!s8E!%rrE'!s8W&u!WW2u!<3#t!!3-"rW%QMO8f3HK'7gM
|
||||
o&p<H4<kaj2IB/UkQ$t7rsp\=2(+*@P&OiVGJW>"Z&\b^r;cis"T\Q&s8N)urrE*"
|
||||
qu6]trrE&u!W`6#rr3$"rr@ZNNW0!FK'7gMo&p<H4<kaj2IB/UkQ$t7rsp\=2(+*@
|
||||
P$V[3AAdHfZ&\b^!!)lq!!*#u!!*#u!!)utr;Zlu!<3!!!<;rs!WN.Os,I$YQ\+FQ
|
||||
kjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8P*0QqCM1NEj0=XBrr<&qrr<&urr<&urr<&u
|
||||
rr<&urrN3#!<3!"!<3&srr<%Ns,I$YQ\+FQkjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8
|
||||
P*0QqCM1NEj0=XBrr<&rrriE&!<<'!rr2rurr2rurr3$"rrE&u!W`6#rr3$"rr@ZN
|
||||
NW0!FK'7gMo&p<H4<b[i2IB/UkQ$t7rsp\=2(+*@P%ncJB>W]hZ&\b^qu?ct!<3!&
|
||||
!<<'!!<3&ts8;ourrE&u!W`9#rW)rt!<<+Os,[0[Q\+FQkjmpB6p)Y3,rT+(r9+-I
|
||||
lMhAH2)Qb8P*0QqCM1NEj0=Vrs+::/rrAC;k^r$hkQaL<+rVac?VLC]!13!N%kTXr
|
||||
-\[_HC27Tt_W0[]Ne7:_s5<nWQ\+FQkjmpB6p)Y3,rT+(r9+-IlMhAH2)Qb8P*0Qq
|
||||
CM1NEj0=Jns+::/rrAC;k^r$hkQaL<+rVac?VLC]!13!N%nfYm:ipu.AnPafOe88&
|
||||
m"57hs5<nWQ\+FQkjmpB6p)Y3,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2IB/U
|
||||
kQ$s$s+:9]rrAC;k^r$hkQaL<+rVac?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7:K
|
||||
9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)Y3,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj
|
||||
2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!
|
||||
)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H
|
||||
4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh
|
||||
#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2YrK'7gM
|
||||
o&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]!1/<$
|
||||
K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&\c2Yr
|
||||
K'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;K)`C]
|
||||
!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-IK)^H&
|
||||
\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]!1/<;
|
||||
K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(r9+-I
|
||||
K)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd?VLC]
|
||||
!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4,rT+(
|
||||
r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<,8qjd
|
||||
?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB6p)\4
|
||||
,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$hkQaL<
|
||||
,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7:K9`4)SQ\,6hs1/.0Q\+FQkjmpB
|
||||
6p)\4,rT+(r9+-IK)^H&\c2YrK'7gMo&p<H4<kaj2IB/UkQ$s$s+:9]rrAC;k^r$h
|
||||
kQaL<,8qjd?VLC]!1/<;K)`C]!1/<$K';dh#=L[!)C7=L9`4)SQ\,6hs1/.0Q\+FQ
|
||||
kjmpB6p)Y3,r]1)r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2d]8VkQ$s$s+:9]rrAC;
|
||||
k^r$hkQaL<+rVad?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7=L9`4)SQ\,6hs1/.0
|
||||
Q\+FQkjmpB6p)Y3,r]1)r9+-IK)^H&\c2YrK'7gMo&p<H4<b[i2d]8VkQ$s$s+:9]
|
||||
rrAC;k^r$hkQaL<+rVad?VLC]!1/<;K)`C]!1/<$K';dh#=LZu)C7=L9`4)SQ\,6h
|
||||
s1/.0Q\+FQkjmpB6p)Y3,r]1)r9/a!JsXNElMlJ"K'<$o#=LZu)C7=L9S2J[kecQK
|
||||
s+9HdkkXEI6p)Y3,r]1)K'7gM_W^:bK'7gMq</&O4<b[i2IB.0k^r$8kkb;\n"3GU
|
||||
5QXKCkPG41k^r$okQaL<,8qjd?VH(8K':)8qu6bR(gsQH^BD#Z(jPfQs+9HdkkXEI
|
||||
6p)\4,rT+(K'7gM_W^su"4oMWp\FgjLG6dIs+9HdkkXEI6p)\4,rT+(K'7gM_W_"!
|
||||
#,a/qs-/5%qYpWK3/@M5K'7gMq</&O4<kaj2IB.0k^r$8kR%:hk:#g!s#^9Dq#:F]
|
||||
^]4=ck^r$okQaL<,8qjd?VH(8K':)8"98Bl\,QC/49.M=rr_.,p]#j/K'<$o#=L[!
|
||||
)C7:K9S2J[kecNbs.<]trrP:_4SSjWLNriNk^r$okQaL<,8qjd?VH(8K':)8!rj,#
|
||||
rVls^!'Gu7,lj_;rrF8"K'7gMq</&O4<kaj2IB/UkQ9i%gOe/:g4IlAeH*EMr;QaZ
|
||||
rW!'`,ldq?r;QeBLP"`AkkXEI6p)\4,rT+(r9+7>i/UH^0S2"%0EHZQr;R$b!!';(
|
||||
o/m"!r;Qf,8:p&WkkXEI6p)\4,rT+(r9+7<NciQts+:9orrHN"r;Qg\!'L8\"/>hr
|
||||
bl.PBa#J\7K'<$o#=L[!)C7:K9`4)Uge5hBrdt-lrW--!r;Qg\!'L8\"3^`Fbl.PB
|
||||
h]RO7K'<$o#=L[!)C7=L9`4)TgG&X)K):/sbkhESQi-jb49.MCrr^IF!6kEA!P^mO
|
||||
k^r$okQaL<,8qje?VLC]!o,L+K)(#ob4u'nGl7RC49-],rr[rT-0G1+!O#=Ok^r$o
|
||||
kQaL<,8qje?VLC]!SfA\pO`.]pAr;or;R$b!!#m?UEon;r;Qe*T7Z9YkkXEI6p)\4
|
||||
,r]1)r9+1:0S8ulo`5$me+E_A!;6$a!8@)H!!'b+!rj\#rVls^!+R>S!!+D!rVlrn
|
||||
)"3(?K'<$o#=L[!)C7=L9`4)TgbA!cquH-W!<<,To`5$mrq-9l!8$lE!!)W`!<<,[
|
||||
o`5$mp@SFd!8-rF!!)W`!<<-!o`5$me+EeB^Hhbt#F'qWk&`_-k5>5\BUAaNk^r$o
|
||||
kQaL<,8qje?VLC]!o,L&lgt2X!9s+V!!(gH!<<,JoDnple+<Y@!;?$c!!([D!<<,k
|
||||
oDnplht-pL!:oaas8Qc!o)Ag43<0#1k^r$okQaL<,8qje?VLC]"5GU&o^)/M!!)rg
|
||||
"TSPo!;#g\!<2Tg!!2]_r;ZlioDJ[eo*YNuo)S@^!;#d^!;$*gqXaXc"7lKmoDARg
|
||||
oDSahoDJ[doDJXqoCDq^oCDq^oCMn\$hF>uo)Jd^o)Jd^oDJXlo)Jd^oDJXioCMk[
|
||||
r::F!!:p3^!!)W^!!)Tj!;#g\!;uHf!!`#p!:p3^oDJXioCMk[!;$0iqt'ad!V>p]
|
||||
!!Vuc!!)W^r;cigr;Zihr;Zul!!)W^r;ZlioDAUWo)Sgko^`4cs7[r!o`#'_0\?@)
|
||||
K'7gMq</&O4<kaj2d]8VkQBTooCM>>!<<,to)/Omnc/[\nc/[fncSpmnc/[hnc]!n
|
||||
o'ub\rUTme%IsK!o'ub\nc/[\nc/[enc8^jrpg^&!:g*io'ub\o'ub\nc/[\nc/[g
|
||||
ndb^#o'ub\nc/[\nc/[\!!)ug$NL1t!!)T\!!)Qi!<)I!!!)Qi!:o[\!:g*io'ub\
|
||||
rUTme&Fof$o'ub\nc/[\!!)T\!!)ug!rr>lo)/P#nc/[\nc/[\!!)T\!!)T\!!)ug
|
||||
!<<,une(p&o'ub\nc/[\!!)T\!!)Qi!<)Hh!!*#h%fcV#!!)T\!!)Qi!:o[\!:KCY
|
||||
!!)``rr3&G.$sZ-!k0Serr7T6K'<$o#=L[!)C7=L9`4)VgbA?km.(/W!;uBg!!*#h
|
||||
qZ$Zfo)&Ihnc/[ho(rFcnc8^jrpgKu!:o[\!:g*io'ub\o)/Oinc/[hndPR!nc/[\
|
||||
nc/[\nc/[\qZ-TcqZ$Zfo)/Ojo'ub\rUL6p!:g*io'ub\o)/P#o'ub\nc/[\nc/[\
|
||||
!!)T\!!)ug!<<-!nd,9ro'ub\nc/[\qZ-Tc"TSPnnc/[hndkd$o'ub\nc/[\nc/[\
|
||||
nc/[go)/Oho()YX"7cElo(rCgnc/[gnc8^jrpgR"!:g*io'ub\nc/[\nc/[go)/Og
|
||||
o)/Ranc/[ao)8Rjmq=]4qYpZ\?qBJZs+9HdkkXEI6p)\4,r]1)r9+7<0_4f$nGrUi
|
||||
r:'df!<2Kh!!)re#QOkpnGiRZ!!*#g!<<,qnGrUirp^Bs!:fRZ!:^$hnaQSZqsa[e
|
||||
!<2L!!!)Nh!:fRZ!:fRZ!:^$hq=+Ic!;l<b!!Dc]!!)uf$31(r!!)QZ!!)QZr;[E!
|
||||
!!)Nh!:fRZ!:^$hnaQSZrUBmg!<2Kr!!)QZ!!)Nh!:^$hq=+Ug!:fRZ!<2L"!!)QZ
|
||||
!!)Nh!:fRZ!:fRZ!;uBc!!;Zj!;u?i!!)Nh!;u?f!!)uf!<<-!nIGU"nGiRZnGiRZ
|
||||
!!)QZ!!)HW!<<,nnb`=na!`WkLVJn"5T$-js+9HdkkXEI6p)\4,r]1)r9+7<0_+]"
|
||||
n,WLhr9s^e!<2Hg!!)rd#QOkon,NIX!!*#f!<<,qn,WLhrpU<r!:]IX!:TsgnF-DX
|
||||
qsXUd!<2Hu!!)Kg!:]IX!:]IX!:Tsgq="Cb!;u<l!!)NX!!)Kg!<)Bm!!)Kg!:]IX
|
||||
!<)C"!!)Kg!:TsgnF-DXn,NIXn,NIen,WLhrpU9q!:]IX!:Tsgn,NIan-&dlnF-DX
|
||||
rpUI!!:]IX!:TsgnF-DXnF-DXqX=Uf!:Tsgr9sgh!:Tsgr9s^e!<)Bf!!*#f%fcV!
|
||||
!!)NX!!)Kg!:]IX!:]IY!!)Z\q>UZFIs=4tJ%tgZK'7gMq</&O4<kaj2d]8VkQBTo
|
||||
naYr7qu?ff!!)uequ?cenGE7enF6DW!V#UV!<)Bf!!)uequ?rj!!)NX!!)lbrW!Ju
|
||||
!!)Kg!:]IX!:]IX!:]LU!;u?a!!r&o!:]IX!:]LV!!Mck!:]LU!!)Ne!!Vl]!!)NX
|
||||
r;[)ln,NIXn,NIen,WLhrUB^b"RlBknF6>UrU9sj!:]IX!<)Ec!"8;c!!)NX!!)NX
|
||||
!!)uer;cidqu?lh!!)NXqu?cenGN=fnF6DW"RlBknF6AV#Oq3_!:]IX!:oU[!!)3O
|
||||
"RkX90^ODTK';dh#=L[!)C7=L9`4)VgbA6eK("<[_!_Eol/FD`K'7gMo&p<H4<b[i
|
||||
2d]8VkQ0HmK("<[^@)3lkM\,^K'7gMo&p<H4<b[i2d]8VkQ0HmK'IsQ^?PjaiS6-S
|
||||
K'7gMo&p<H4<b[i2d]8VkQTd-`89>+K&2+9_qkRQgXj#%mt0bTkjmpB6p)Y3,r]1)
|
||||
r9+7?IVGj7d"9W[cih\&AqT],k^r$hkQaL<+rVad?VLC]"6A[.97ejL0Y]:D5_S_#
|
||||
K'7gMo&p<H4<b[i2d]8UkQC2@oCRY-iUqftj7rWH"8;H]l[n>PkjmpB6p)Y3,r]1)
|
||||
K'7gMK'7gMUZ_qN4<b[i2d]71k^r#Mk^r#nkQaL<+rVad?VH(8K'7gMK'8un#=LZu
|
||||
)C7=L9S2J[k^r#MkbI>H6p)Y3,r]1)K'7gMK'7gMUZ`"P4<kaj2d]7QRf8TQP_,'M
|
||||
P(JjKP-:#KPl@!WS>&D6,8qje?VJtmrl,&X_SO(a_"kb=^APZr]RmeJ]RmfI]`#GB
|
||||
^&GeT`QU_4,8qje?VKM:rn@G+rn-hopX];m!S,`re:Q/$dt6&#e)AaUdeqPreC)do
|
||||
rm_D.gI+.K)C7=L9^D!CkQ'fFkk"!5k547ljFZHEjFZIGjS\'8iW.s9iX"R44<kaj
|
||||
2d]8Vn+5uCm/cS?qs3k=K'@mOK'@mOjQQ^/kks]AkR$G86p)\4,r]1)rU'dTmI'E;
|
||||
mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)L
|
||||
lg+H5q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5
|
||||
q<@kA!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA
|
||||
!U8j#k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#
|
||||
k^r#Mk^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#M
|
||||
k^r$TkkXBLk2tji6p)\4,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$T
|
||||
kkXBLZa8iX6p)Y3,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBL
|
||||
Za9\p6p)Y3,r]1)rU'dTmI'E;mJ6)Llg+H5q<@kA!U8j#k^r#Mk^r$TkkXBMk5YJE
|
||||
6p)Y3,r]1)mJcDOm.9Q;lM]rLkih9qqrmn>K'%[IK'%[Ii8t%$qr[k=#=LZu)C7=L
|
||||
9_@ZFl4*"Bkih9qkih9qkih9qqrmn>K'%[IK'%[IiT:.%roO`tZf^DVZfU::4<b[i
|
||||
2d]8Ulh9W>kl^/5l08*/pZDS>k5OOqk(;`Ik(;aOjq"f)s5gSns5cX2+rVad?VL@]
|
||||
rp'CFp#u57!TiGAk(;]HjauTGjj`B*jT#8AjT#8@6p)Y3,r]1)kND'mp?2A9nDs]3
|
||||
jS.\die$0Aie$1MiWeH&j5T(Yj8%[>6p)Y3,r]1)o&BQ*p##l.hu2Jbhh'a;hh'b<
|
||||
h\G#)Za8NFZa8NFZa8KD6p)Y3,r]1)o\B,okh:XAK%Yb/K%],9'=5%FfsA$bfsA$b
|
||||
fL.hG)C7=L9^^O(f(%:Be:Q2%e:Q3-e.hr_eC=NueC4HtdmQ;B)C7=L9\eFsh;d;f
|
||||
gOe.2g4J%1g=P$dg"=qF4<b[i2bm^Rnk+L%Jjb2YJjcq5#Wsaa)C7=2:.=_<JinWI
|
||||
JinWIZTJ@L/gD8WYTr-Ong!]LnK[TKiZn"<dNdcrnK[TKJg8;\nfk=`![&C$Jf94Z
|
||||
Jf94ZS/M
|
||||
~>
|
||||
grestore
|
||||
currentdict /inputf undef
|
||||
currentdict /pstr undef
|
||||
File diff suppressed because it is too large.
Load diff
+983
-1
@@ -2060,6 +2060,988 @@ iptables:
|
||||
iptables -A INPUT -p tcp -{}-destination-port 8002 -j REJECT
|
||||
\end{verbatim}
|
||||
|
||||
%% Chapter Xen Mandatory Access Control Framework
|
||||
\chapter{sHype/Xen Access Control}
|
||||
|
||||
The Xen mandatory access control framework is an implementation of the
|
||||
sHype Hypervisor Security Architecture
|
||||
(www.research.ibm.com/ssd\_shype). It permits or denies communication
|
||||
and resource access of domains based on a security policy. The
|
||||
mandatory access controls are enforced in addition to the Xen core
|
||||
controls, such as memory protection. They are designed to remain
|
||||
transparent during normal operation of domains (policy-conform
|
||||
behavior) but to intervene when domains move outside their intended
|
||||
sharing behavior. This chapter will describe how the sHype access
|
||||
controls in Xen can be configured to prevent viruses from spilling
|
||||
over from one into another workload type and secrets from leaking from
|
||||
one workload type to another. sHype/Xen depends on the correct
|
||||
behavior of Domain0 (cf previous chapter).
|
||||
|
||||
Benefits of configuring sHype/ACM in Xen include:
|
||||
\begin{itemize}
|
||||
\item robust workload and resource protection effective against rogue
|
||||
user domains
|
||||
\item simple, platform- and operating system-independent security
|
||||
policies (ideal for heterogeneous distributed environments)
|
||||
\item safety net with minimal performance overhead in case operating
|
||||
system security is missing, does not scale, or fails
|
||||
\end{itemize}
|
||||
|
||||
These benefits are very valuable because today's operating systems
|
||||
become increasingly complex and often have no or insufficient
|
||||
mandatory access controls. (Discretionary access controls, supported
|
||||
by of most operating systems, are not effective against viruses or
|
||||
misbehaving programs.) Where mandatory access control exists (e.g.,
|
||||
SELinux), they usually deploy complex and difficult to understand
|
||||
security policies. Additionally, multi-tier applications in business
|
||||
environments usually require different types of operating systems
|
||||
(e.g., AIX, Windows, Linux) which cannot be configured with compatible
|
||||
security policies. Related distributed transactions and workloads
|
||||
cannot be easily protected on the OS level. The Xen access control
|
||||
framework steps in to offer a coarse-grained but very robust security
|
||||
layer and safety net in case operating system security fails or is
|
||||
missing.
|
||||
|
||||
To control sharing between domains, Xen mediates all inter-domain
|
||||
communication (shared memory, events) as well as the access of domains
|
||||
to resources such as disks. Thus, Xen can confine distributed
|
||||
workloads (domain payloads) by permitting sharing among domains
|
||||
running the same type of workload and denying sharing between pairs of
|
||||
domains that run different workload types. We assume that--from a Xen
|
||||
perspective--only one workload type is running per user domain. To
|
||||
enable Xen to associate domains and resources with workload types,
|
||||
security labels including the workload types are attached to domains
|
||||
and resources. These labels and the hypervisor sHype controls cannot
|
||||
be manipulated or bypassed and are effective even against rogue
|
||||
domains.
|
||||
|
||||
\section{Overview}
|
||||
This section gives an overview of how workloads can be protected using
|
||||
the sHype mandatory access control framework in Xen.
|
||||
Figure~\ref{fig:acmoverview} shows the necessary steps in activating
|
||||
the Xen workload protection. These steps are described in detail in
|
||||
Section~\ref{section:acmexample}.
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\includegraphics[width=13cm]{figs/acm_overview.eps}
|
||||
\caption{Overview of activating sHype workload protection in Xen.
|
||||
Section numbers point to representative examples.}
|
||||
\label{fig:acmoverview}
|
||||
\end{figure}
|
||||
|
||||
First, the sHype/ACM access control must be enabled in the Xen
|
||||
distribution and the distribution must be built and installed (cf
|
||||
Subsection~\ref{subsection:acmexampleconfigure}). Before we can
|
||||
enforce security, a Xen security policy must be created (cf
|
||||
Subsection~\ref{subsection:acmexamplecreate}) and deployed (cf
|
||||
Subsection~\ref{subsection:acmexampleinstall}). This policy defines
|
||||
the workload types differentiated during access control. It also
|
||||
defines the rules that compare workload types of domains and resources
|
||||
to provide access decisions. Workload types are represented by
|
||||
security labels that can be attached to domains and resources (cf
|
||||
Subsections~\ref{subsection:acmexamplelabeldomains}
|
||||
and~\ref{subsection:acmexamplelabelresources}). The functioning of
|
||||
the active sHype/Xen workload protection is demonstrated using simple
|
||||
resource assignment, and domain creation tests in
|
||||
Subsection~\ref{subsection:acmexampletest}.
|
||||
Section~\ref{section:acmpolicy} describes the syntax and semantics of
|
||||
the sHype/Xen security policy in detail and introduces briefly the
|
||||
tools that are available to help create valid security policies.
|
||||
|
||||
The next section describes all the necessary steps to create, deploy,
|
||||
and test a simple workload protection policy. It is meant to enable
|
||||
anybody to quickly try out the sHype/Xen workload protection. Those
|
||||
readers who are interested in learning more about how the sHype access
|
||||
control in Xen works and how it is configured using the XML security
|
||||
policy should read Section~\ref{section:acmpolicy} as well.
|
||||
Section~\ref{section:acmlimitations} concludes this chapter with
|
||||
current limitations of the sHype implementation for Xen.
|
||||
|
||||
\section{Xen Workload Protection Step-by-Step}
|
||||
\label{section:acmexample}
|
||||
|
||||
What you are about to do consists of the following sequence:
|
||||
\begin{itemize}
|
||||
\item configure and install sHype/Xen
|
||||
\item create a simple workload protection security policy
|
||||
\item deploy the sHype/Xen security policy
|
||||
\item associate domains and resources with workload labels,
|
||||
\item test the workload protection
|
||||
\end{itemize}
|
||||
The essential commands to create and deploy a sHype/Xen security
|
||||
policy are numbered throughout the following sections. If you want a
|
||||
quick-guide or return at a later time to go quickly through this
|
||||
demonstration, simply look for the numbered commands and apply them in
|
||||
order.
|
||||
|
||||
\subsection{Configuring/Building sHype Support into Xen}
|
||||
\label{subsection:acmexampleconfigure}
|
||||
First, we need to configure the access control module in Xen and
|
||||
install the ACM-enabled Xen hypervisor. This step installs security
|
||||
tools and compiles sHype/ACM controls into the Xen hypervisor.
|
||||
|
||||
To enable sHype/ACM in Xen, please edit the Config.mk file in the top
|
||||
Xen directory.
|
||||
|
||||
\begin{verbatim}
|
||||
(1) In Config.mk
|
||||
Change: ACM_SECURITY ?= n
|
||||
To: ACM_SECURITY ?= y
|
||||
\end{verbatim}
|
||||
|
||||
Then install the security-enabled Xen environment as follows:
|
||||
|
||||
\begin{verbatim}
|
||||
(2) # make world
|
||||
# make install
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Creating A WLP Policy in 3 Simple Steps with ezPolicy}
|
||||
\label{subsection:acmexamplecreate}
|
||||
|
||||
We will use the ezPolicy tool to quickly create a policy that protects
|
||||
workloads. You will need both the Python and wxPython packages to run
|
||||
this tool. To run the tool in Domain0, you can download the wxPython
|
||||
package from www.wxpython.org or use the command
|
||||
\verb|yum install wxPython| in Redhat/Fedora. To run the tool on MS
|
||||
Windows, you also need to download the Python package from
|
||||
www.python.org. After these packages are installed, start the ezPolicy
|
||||
tool with the following command:
|
||||
|
||||
\begin{verbatim}
|
||||
(3) # xensec_ezpolicy
|
||||
\end{verbatim}
|
||||
|
||||
Figure~\ref{fig:acmezpolicy} shows a screen-shot of the tool. The
|
||||
following steps show you how to create the policy shown in
|
||||
Figure~\ref{fig:acmezpolicy}. You can use \verb|<CTRL>-h| to pop up a
|
||||
help window at any time. The indicators (a), (b), and (c) in
|
||||
Figure~\ref{fig:acmezpolicy} show the buttons that are used during the
|
||||
3 steps of creating a policy:
|
||||
\begin{enumerate}
|
||||
\item defining workloads
|
||||
\item defining run-time conflicts
|
||||
\item translating the workload definition into a sHype/Xen access
|
||||
control policy
|
||||
\end{enumerate}
|
||||
|
||||
\paragraph{Defining workloads.} Workloads are defined for each
|
||||
organization and department that you enter in the left panel. Please
|
||||
use the ``New Org'' button (a) to create the organizations ``Avis'',
|
||||
``Hertz'', ``CocaCola'', and ``PepsiCo''.
|
||||
|
||||
You can refine an organization to differentiate between multiple
|
||||
department workloads by right-clicking the organization and selecting
|
||||
\verb|Add Department| (or selecting an organization and pressing
|
||||
\verb|<CRTL>-a|). Create department workloads ``Intranet'',
|
||||
``Extranet'', ``HumanResources'', and ``Payroll'' for the ``CocaCola''
|
||||
organization and department workloads ``Intranet'' and ``Extranet''
|
||||
for the ``PepsiCo'' organization. The resulting layout of the tool
|
||||
should be similar to the left panel shown in
|
||||
Figure~\ref{fig:acmezpolicy}.
|
||||
|
||||
\paragraph{Defining run-time conflicts.} Workloads that shall be
|
||||
prohibited from running concurrently on the same hypervisor platform
|
||||
are grouped into ``Run-time Exclusion rules'' on the right panel of
|
||||
the window.
|
||||
|
||||
To prevent PepsiCo and CocaCola workloads (including their
|
||||
departmental workloads) from running simultaneously on the same
|
||||
hypervisor system, select the organization ``PepsiCo'' and, while
|
||||
pressing the \verb|<CTRL>|-key, select the organization ``CocaCola''.
|
||||
Now press the button (b) named ``Create run-time exclusion rule from
|
||||
selection''. A popup window will ask for the name for this run-time
|
||||
exclusion rule (enter a name or just hit \verb|<ENTER>|). A rule will
|
||||
appear on the right panel. The name is used as reference only and does
|
||||
not affect the hypervisor policy.
|
||||
|
||||
Repeat the process to create a run-time exclusion rule just for the
|
||||
department workloads CocaCola.Extranet and CocaCola.Payroll.
|
||||
|
||||
\begin{figure}[htb]
|
||||
\centering
|
||||
\includegraphics[width=13cm]{figs/acm_ezpolicy.eps}
|
||||
\caption{Final layout including workload definition and Run-time Exclusion rules.}
|
||||
\label{fig:acmezpolicy}
|
||||
\end{figure}
|
||||
|
||||
The resulting layout of your window should be similar to
|
||||
Figure~\ref{fig:acmezpolicy}. Save this workload definition by
|
||||
selecting ``Save Workload Definition as ...'' in the ``File'' menu
|
||||
(c). This workload definition can be later refined if required.
|
||||
|
||||
\paragraph{Translating the workload definition into a sHype/Xen access
|
||||
control policy.} To translate the workload definition into a access
|
||||
control policy understood by Xen, please select the ``Save as Xen ACM
|
||||
Security Policy'' in the ``File'' menu (c). Enter the following policy
|
||||
name in the popup window: \verb|example.chwall_ste.test-wld|. If you
|
||||
are running ezPolicy in Domain0, the resulting policy file
|
||||
test-wld\_security-policy.xml will automatically be placed into the
|
||||
right directory (/etc/xen/acm-security/ policies/example/chwall\_ste).
|
||||
If you run the tool on another system, then you need to copy the
|
||||
resulting policy file into Domain0 before continuing. See
|
||||
Section~\ref{subsection:acmnaming} for naming conventions of security
|
||||
policies.
|
||||
|
||||
\subsection{Deploying a WLP Policy}
|
||||
\label{subsection:acmexampleinstall}
|
||||
To deploy the workload protection policy we created in
|
||||
Section~\ref{subsection:acmexamplecreate}, we create a policy
|
||||
representation (test-wld.bin) that can be loaded into the Xen
|
||||
hypervisor and we configure Xen to actually load this policy at
|
||||
startup time.
|
||||
|
||||
The following command translates the source policy representation
|
||||
into a format that can be loaded into Xen with sHype/ACM support.
|
||||
Refer to the \verb|xm| man page for further details:
|
||||
|
||||
\begin{verbatim}
|
||||
(4) # xm makepolicy example.chwall_ste.test-wld
|
||||
\end{verbatim}
|
||||
|
||||
The easiest way to install a security policy for Xen is to include the
|
||||
policy in the boot sequence. The following command does just this:
|
||||
|
||||
\begin{verbatim}
|
||||
(5) # xm cfgbootpolicy example.chwall_ste.test-wld
|
||||
\end{verbatim}
|
||||
|
||||
\textit{Alternatively, if this command fails} (e.g., because it cannot
|
||||
identify the Xen boot entry), you can manually install the policy in 2
|
||||
steps. First, manually copy the policy binary file into the boot
|
||||
directory:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# cp /etc/xen/acm-security/policies/example/chwall_ste/test-wld.bin \
|
||||
/boot/example.chwall_ste.test-wld.bin
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Second, manually add a module line to your Xen boot entry so that grub
|
||||
loads this policy file during startup:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
title Xen (2.6.16.13)
|
||||
root (hd0,0)
|
||||
kernel /xen.gz dom0_mem=2000000 console=vga
|
||||
module /vmlinuz-2.6.16.13-xen ro root=/dev/hda3
|
||||
module /initrd-2.6.16.13-xen.img
|
||||
module /example.chwall_ste.test-wld.bin
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Now reboot into this Xen boot entry to activate the policy and the
|
||||
security-enabled Xen hypervisor.
|
||||
|
||||
\begin{verbatim}
|
||||
(6) # reboot
|
||||
\end{verbatim}
|
||||
|
||||
After reboot, check if security is enabled:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm list --label
|
||||
Name ID Mem(MiB) VCPUs State Time(s) Label
|
||||
Domain-0 0 1949 4 r----- 163.9 SystemManagement
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
If the security label at the end of the line says ``INACTIV'' then the
|
||||
security is not enabled. Verify the previous steps. Note: Domain0 is
|
||||
assigned a default label (see \verb|bootstrap| policy attribute
|
||||
explained in Section~\ref{section:acmpolicy}). All other domains must
|
||||
be labeled in order to start on this sHype/ACM-enabled Xen hypervisor
|
||||
(see following sections for labeling domains and resources).
|
||||
|
||||
\subsection{Labeling Domains}
|
||||
\label{subsection:acmexamplelabeldomains}
|
||||
You should have a Xen domain configuration file that looks like the
|
||||
following (Note: www.jailtime.org or www.xen-get.org might be good
|
||||
places to look for example domU images). The following configuration
|
||||
file defines \verb|domain1|:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# cat domain1.xm
|
||||
kernel = "/boot/vmlinuz-2.6.16.13-xen"
|
||||
memory = 128
|
||||
name = "domain1"
|
||||
vif = [ '' ]
|
||||
dhcp = "dhcp"
|
||||
disk = ['file:/home/xen/dom_fc5/fedora.fc5.img,sda1,w', \
|
||||
'file:/home/xen/dom_fc5/fedora.swap,sda2,w']
|
||||
root = "/dev/sda1 ro"
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
If you try to start domain1, you will get the following error:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm create domain1.xm
|
||||
Using config file "domain1.xm".
|
||||
domain1: DENIED
|
||||
--> Domain not labeled
|
||||
Checking resources: (skipped)
|
||||
Security configuration prevents domain from starting
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Every domain must be associated with a security label before it can
|
||||
start on sHype/Xen. Otherwise, sHype/Xen would not be able to enforce
|
||||
the policy consistently. The following command prints all domain
|
||||
labels available in the active policy:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm labels type=dom
|
||||
Avis
|
||||
CocaCola
|
||||
CocaCola.Extranet
|
||||
CocaCola.HumanResources
|
||||
CocaCola.Intranet
|
||||
CocaCola.Payroll
|
||||
Hertz
|
||||
PepsiCo
|
||||
PepsiCo.Extranet
|
||||
PepsiCo.Intranet
|
||||
SystemManagement
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Now label domain1 with the CocaCola label and another domain2 with the
|
||||
PepsiCo.Extranet label. Please refer to the xm man page for further
|
||||
information.
|
||||
|
||||
\begin{verbatim}
|
||||
(7) # xm addlabel CocaCola dom domain1.xm
|
||||
# xm addlabel PepsiCo.Extranet dom domain2.xm
|
||||
\end{verbatim}
|
||||
|
||||
Let us try to start the domain again:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm create domain1.xm
|
||||
Using config file "domain1.xm".
|
||||
file:/home/xen/dom_fc5/fedora.fc5.img: DENIED
|
||||
--> res:__NULL_LABEL__ (NULL)
|
||||
--> dom:CocaCola (example.chwall_ste.test-wld)
|
||||
file:/home/xen/dom_fc5/fedora.swap: DENIED
|
||||
--> res:__NULL_LABEL__ (NULL)
|
||||
--> dom:CocaCola (example.chwall_ste.test-wld)
|
||||
Security configuration prevents domain from starting
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
This error indicates that domain1, if started, would not be able to
|
||||
access its image and swap files because they are not labeled. This
|
||||
makes sense because to confine workloads, access of domains to
|
||||
resources must be controlled. Otherwise, domains that are not allowed
|
||||
to communicate or run simultaneously could share data through storage
|
||||
resources.
|
||||
|
||||
\subsection{Labeling Resources}
|
||||
\label{subsection:acmexamplelabelresources}
|
||||
You can use the \verb|xm labels type=res| command to list available
|
||||
resource labels. Let us assign the CocaCola resource label to the domain1
|
||||
image file representing \verb|/dev/sda1| and to its swap file:
|
||||
|
||||
\begin{verbatim}
|
||||
(8) # xm addlabel CocaCola res \
|
||||
file:/home/xen/dom_fc5/fedora.fc5.img
|
||||
Resource file not found, creating new file at:
|
||||
/etc/xen/acm-security/policies/resource_labels
|
||||
# xm addlabel CocaCola res \
|
||||
file:/home/xen/dom_fc5/fedora.swap
|
||||
\end{verbatim}
|
||||
|
||||
Starting \verb|domain1| now will succeed:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm create domain1.xm
|
||||
# xm list --label
|
||||
Name ID Mem(MiB) VCPUs State Time(s) Label
|
||||
domain1 1 128 1 r----- 2.8 CocaCola
|
||||
Domain-0 0 1949 4 r----- 387.7 SystemManagement
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
The following command lists all labeled resources on the
|
||||
system, e.g., to lookup or verify the labeling:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm resources
|
||||
file:/home/xen/dom_fc5/fedora.swap
|
||||
policy: example.chwall_ste.test-wld
|
||||
label: CocaCola
|
||||
file:/home/xen/dom_fc5/fedora.fc5.img
|
||||
policy: example.chwall_ste.test-wld
|
||||
label: CocaCola
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Currently, if a labeled resource is moved to another location, the
|
||||
label must first be manually removed, and after the move re-attached
|
||||
using the xm commands \verb|xm rmlabel| and \verb|xm addlabel|
|
||||
respectively. Please see Section~\ref{section:acmlimitations} for
|
||||
further details.
|
||||
|
||||
\begin{verbatim}
|
||||
(9) Label the resources of domain2 as PepsiCo.Extranet
|
||||
Do not try to start this domain yet
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Testing The Xen Workload Protection}
|
||||
\label{subsection:acmexampletest}
|
||||
We are about to demonstrate how the workload protection works by
|
||||
verifying:
|
||||
\begin{itemize}
|
||||
\item that domains with conflicting workloads cannot run
|
||||
simultaneously
|
||||
\item that domains cannot access resources of other workloads
|
||||
\item that domains cannot exchange network packets if they are not
|
||||
associated with the same workload type
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Test 1: Run-time exclusion rules.} We assume that domain1
|
||||
with the CocaCola label is still running. While domain1 is running,
|
||||
the run-time exclusion set of our policy says that domain2 cannot
|
||||
start because the label of domain1 includes the CHWALL type CocaCola
|
||||
and the label of domain2 includes the CHWALL type PepsiCo. The
|
||||
run-time exclusion rule of our policy enforces that PepsiCo and
|
||||
CocaCola cannot run at the same time on the same hypervisor platform.
|
||||
Once domain1 is stopped or saved, domain2 can start but domain1 can no
|
||||
longer start or be resumed. The ezPolicy tool, when creating the
|
||||
Chinese Wall types for the workload labels, ensures that department
|
||||
workloads inherit the organization type (and with it any organization
|
||||
exclusions).
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm list --label
|
||||
Name ID Mem(MiB) VCPUs State Time(s) Label
|
||||
domain1 2 128 1 -b---- 6.9 CocaCola
|
||||
Domain-0 0 1949 4 r----- 273.1 SystemManagement
|
||||
|
||||
# xm create domain2.xm
|
||||
Using config file "domain2.xm".
|
||||
Error: (1, 'Operation not permitted')
|
||||
|
||||
# xm destroy domain1
|
||||
# xm create domain2.xm
|
||||
Using config file "domain2.xm".
|
||||
Started domain domain2
|
||||
|
||||
# xm list --label
|
||||
Name ID Mem(MiB) VCPUs State Time(s) Label
|
||||
domain2 4 164 1 r----- 4.3 PepsiCo.Extranet
|
||||
Domain-0 0 1949 4 r----- 298.4 SystemManagement
|
||||
|
||||
# xm create domain1.xm
|
||||
Using config file "domain1.xm".
|
||||
Error: (1, 'Operation not permitted')
|
||||
|
||||
# xm destroy domain2
|
||||
# xm list
|
||||
Name ID Mem(MiB) VCPUs State Time(s)
|
||||
Domain-0 0 1949 4 r----- 391.2
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
You can verify that domains with Avis label can run together with
|
||||
domains labeled CocaCola, PepsiCo, or Hertz.
|
||||
|
||||
\paragraph{Test2: Resource access.} In this test, we will re-label the
|
||||
swap file for domain1 with the Avis resource label. We expect that
|
||||
Domain1 will no longer start because it cannot access this resource.
|
||||
This test checks the sharing abilities of domains, which are defined
|
||||
by the Simple Type Enforcement Policy component.
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
# xm rmlabel res file:/home/xen/dom_fc5/fedora.swap
|
||||
# xm addlabel Avis res file:/home/xen/dom_fc5/fedora.swap
|
||||
# xm resources
|
||||
file:/home/xen/dom_fc5/fedora.swap
|
||||
policy: example.chwall_ste.test-wld
|
||||
label: Avis
|
||||
file:/home/xen/dom_fc5/fedora.fc5.img
|
||||
policy: example.chwall_ste.test-wld
|
||||
label: CocaCola
|
||||
|
||||
# xm create domain1.xm
|
||||
Using config file "domain1.xm".
|
||||
file:/home/xen/dom_fc4/fedora.swap: DENIED
|
||||
--> res:Avis (example.chwall_ste.test-wld)
|
||||
--> dom:CocaCola (example.chwall_ste.test-wld)
|
||||
Security configuration prevents domain from starting
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
\paragraph{Test 3: Communication.} In this test we would verify that
|
||||
two domains with labels Hertz and Avis cannot exchange network packets
|
||||
by using the 'ping' connectivity test. It is also related to the STE
|
||||
policy.{\bf Note:} sHype/Xen does control direct communication between
|
||||
domains. However, domains associated with different workloads can
|
||||
currently still communicate through the Domain0 virtual network. We
|
||||
are working on the sHype/ACM controls for local and remote network
|
||||
traffic through Domain0. Please monitor the xen-devel mailing list
|
||||
for updated information.
|
||||
|
||||
\section{Xen Access Control Policy}
|
||||
\label{section:acmpolicy}
|
||||
|
||||
This section describes the sHype/Xen access control policy in detail.
|
||||
It gives enough information to enable the reader to write custom
|
||||
access control policies and to use the available Xen policy tools. The
|
||||
policy language is expressive enough to specify most symmetric access
|
||||
relationships between domains and resources efficiently.
|
||||
|
||||
The Xen access control policy consists of two policy components. The
|
||||
first component, called Chinese Wall (CHWALL) policy, controls which
|
||||
domains can run simultaneously on the same virtualized platform. The
|
||||
second component, called Simple Type Enforcement (STE) policy,
|
||||
controls the sharing between running domains, i.e., communication or
|
||||
access to shared resources. The CHWALL and STE policy components can
|
||||
be configured to run alone, however in our examples we will assume
|
||||
that both policy components are configured together since they
|
||||
complement each other. The XML policy file includes all information
|
||||
needed by Xen to enforce the policies.
|
||||
|
||||
Figures~\ref{fig:acmxmlfilea} and \ref{fig:acmxmlfileb} show a fully
|
||||
functional but very simple example policy for Xen. The policy can
|
||||
distinguish two workload types \verb|CocaCola| and \verb|PepsiCo| and
|
||||
defines the labels necessary to associate domains and resources with
|
||||
one of these workload types. The XML Policy consists of four parts:
|
||||
\begin{enumerate}
|
||||
\item policy header including the policy name
|
||||
\item Simple Type Enforcement block
|
||||
\item Chinese Wall Policy block
|
||||
\item label definition block
|
||||
\end{enumerate}
|
||||
|
||||
\begin{figure}
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
01 <?xml version="1.0" encoding="UTF-8"?>
|
||||
02 <!-- Auto-generated by ezPolicy -->
|
||||
03 <SecurityPolicyDefinition
|
||||
xmlns="http://www.ibm.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation=
|
||||
"http://www.ibm.com ../../security_policy.xsd ">
|
||||
04 <PolicyHeader>
|
||||
05 <PolicyName>example.chwall_ste.test</PolicyName>
|
||||
06 <Date>Wed Jul 12 17:32:59 2006</Date>
|
||||
07 </PolicyHeader>
|
||||
08
|
||||
09 <SimpleTypeEnforcement>
|
||||
10 <SimpleTypeEnforcementTypes>
|
||||
11 <Type>SystemManagement</Type>
|
||||
12 <Type>PepsiCo</Type>
|
||||
13 <Type>CocaCola</Type>
|
||||
14 </SimpleTypeEnforcementTypes>
|
||||
15 </SimpleTypeEnforcement>
|
||||
16
|
||||
17 <ChineseWall priority="PrimaryPolicyComponent">
|
||||
18 <ChineseWallTypes>
|
||||
19 <Type>SystemManagement</Type>
|
||||
20 <Type>PepsiCo</Type>
|
||||
21 <Type>CocaCola</Type>
|
||||
22 </ChineseWallTypes>
|
||||
23
|
||||
24 <ConflictSets>
|
||||
25 <Conflict name="RER1">
|
||||
26 <Type>CocaCola</Type>
|
||||
27 <Type>PepsiCo</Type>
|
||||
28 </Conflict>
|
||||
29 </ConflictSets>
|
||||
30 </ChineseWall>
|
||||
31
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
\caption{Example XML security policy file -- Part I: Types and Rules Definition.}
|
||||
\label{fig:acmxmlfilea}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Policy Header and Policy Name}
|
||||
\label{subsection:acmnaming}
|
||||
Lines 1-2 (cf Figure~\ref{fig:acmxmlfilea}) include the usual XML
|
||||
header. The security policy definition starts in Line 3 and refers to
|
||||
the policy schema. The XML-Schema definition for the Xen policy can be
|
||||
found in the file
|
||||
\textit{/etc/xen/acm-security/policies/security-policy.xsd}. Examples
|
||||
for security policies can be found in the example subdirectory. The
|
||||
acm-security directory is only installed if ACM security is configured
|
||||
during installation (cf Section~\ref{subsection:acmexampleconfigure}).
|
||||
|
||||
The \verb|Policy Header| spans lines 4-7. It includes a date field and
|
||||
defines the policy name \verb|example.chwall_ste.test|. It can also
|
||||
include optional fields that are not shown and are for future use (see
|
||||
schema definition).
|
||||
|
||||
The policy name serves two purposes: First, it provides a unique name
|
||||
for the security policy. This name is also exported by the Xen
|
||||
hypervisor to the Xen management tools in order to ensure that both
|
||||
enforce the same policy. We plan to extend the policy name with a
|
||||
digital fingerprint of the policy contents to better protect this
|
||||
correlation. Second, it implicitly points the xm tools to the
|
||||
location where the XML policy file is stored on the Xen system.
|
||||
Replacing the colons in the policy name by slashes yields the local
|
||||
path to the policy file starting from the global policy directory
|
||||
\verb|/etc/xen/acm-security/policies|. The last part of the policy
|
||||
name is the prefix for the XML policy file name, completed by
|
||||
\verb|-security_policy.xml|. Consequently, the policy with the name
|
||||
\verb|example.chwall_ste.test| can be found in the XML policy file
|
||||
named \verb|test-security_policy.xml| that is stored in the local
|
||||
directory \verb|example/chwall_ste| under the global policy directory.
|
||||
|
||||
\subsection{Simple Type Enforcement Policy Component}
|
||||
|
||||
The Simple Type Enforcement (STE) policy controls which domains can
|
||||
communicate or share resources. This way, Xen can enforce confinement
|
||||
of workload types by confining the domains running those workload
|
||||
types. The mandatory access control framework enforces its policy when
|
||||
domains access intended ways of communication or cooperation (shared
|
||||
memory, events, shared resources such as block devices). It builds on
|
||||
top of the core hypervisor isolation, which restricts the ways of
|
||||
inter-communication to those intended means. STE does not protect or
|
||||
intend to protect from covert channels in the hypervisor or hardware;
|
||||
this is an orthogonal problem that can be mitigated by using the
|
||||
Run-time Exclusion rules described above or by fixing the problem in
|
||||
the core hypervisor.
|
||||
|
||||
Xen controls sharing between domains on the resource and domain level
|
||||
because this is the abstraction the hypervisor and its management
|
||||
understand naturally. While this is coarse-grained, it is also very
|
||||
reliable and robust and it requires minimal changes to implement
|
||||
mandatory access controls in the hypervisor. It enables platform- and
|
||||
operation system-independent policies as part of a layered security
|
||||
approach.
|
||||
|
||||
Lines 9-15 (cf Figure~\ref{fig:acmxmlfilea}) define the Simple Type
|
||||
Enforcement policy component. Essentially, they define the workload
|
||||
type names \verb|SystemManagement|, \verb|PepsiCo|, and
|
||||
\verb|CocaCola| that are available in the STE policy component. The
|
||||
policy rules are implicit: Xen permits a domain to communicate with
|
||||
another domain if and only if the labels of the domains share an
|
||||
common STE type. Xen permits a domain to access a resource if and
|
||||
only if the labels of the domain and the resource share a common STE
|
||||
workload type.
|
||||
|
||||
\subsection{Chinese Wall Policy Component}
|
||||
|
||||
The Chinese Wall security policy interpretation of sHype enables users
|
||||
to prevent certain workloads from running simultaneously on the same
|
||||
hypervisor platform. Run-time Exclusion rules (RER), also called
|
||||
Conflict Sets, define a set of workload types that are not permitted
|
||||
to run simultaneously. Of all the workloads specified in a Run-time
|
||||
Exclusion rule, at most one type can run on the same hypervisor
|
||||
platform at a time. Run-time Exclusion Rules implement a less
|
||||
rigorous variant of the original Chinese Wall security component. They
|
||||
do not implement the *-property of the policy, which would require to
|
||||
restrict also types that are not part of an exclusion rule once they
|
||||
are running together with a type in an exclusion rule (please refer to
|
||||
http://www.gammassl.co.uk/topics/chinesewall.html for more information
|
||||
on the original Chinese Wall policy).
|
||||
|
||||
Xen considers the \verb|ChineseWallTypes| part of the label for the
|
||||
enforcement of the Run-time Exclusion rules. It is illegal to define
|
||||
labels including conflicting Chinese Wall types.
|
||||
|
||||
Lines 17-30 (cf Figure~\ref{fig:acmxmlfilea}) define the Chinese Wall
|
||||
policy component. Lines 17-22 define the known Chinese Wall types,
|
||||
which coincide here with the STE types defined above. This usually
|
||||
holds if the criteria for sharing among domains and sharing of the
|
||||
hardware platform are the same. Lines 24-29 define one Run-time
|
||||
Exclusion rule:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
<Conflict name="RER1">
|
||||
<Type>CocaCola</Type>
|
||||
<Type>PepsiCo</Type>
|
||||
</Conflict>
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
Based on this rule, Xen enforces that only one of the types
|
||||
\verb|CocaCola| or \verb|PepsiCo| will run on a single hypervisor
|
||||
platform at a time. For example, once a domain assigned a
|
||||
\verb|CocaCola| workload type is started, domains with the
|
||||
\verb|PepsiCo| type will be denied to start. When the former domain
|
||||
stops and no other domains with the \verb|CocaCola| type are running,
|
||||
then domains with the \verb|PepsiCo| type can start.
|
||||
|
||||
Xen maintains reference counts on each running workload type to keep
|
||||
track of which workload types are running. Every time a domain starts
|
||||
or resumes, the reference count on those Chinese Wall types that are
|
||||
referenced in the domain's label are incremented. Every time a domain
|
||||
is destroyed or saved, the reference counts of its Chinese Wall types
|
||||
are decremented. sHype in Xen covers migration and live-migration,
|
||||
which is treated the same way as saving a domain on the source
|
||||
platform and resuming it on the destination platform.
|
||||
|
||||
Reasons why users would want to restrict which workloads or domains
|
||||
can share the system hardware include:
|
||||
|
||||
\begin{itemize}
|
||||
\item Imperfect resource management or control might enable a rogue
|
||||
domain to starve another domain and the workload running in it.
|
||||
\item Redundant domains might run the same workload to increase
|
||||
availability; such domains should not run on the same hardware to
|
||||
avoid single points of failure.
|
||||
\item Imperfect Xen core domain isolation might enable two rogue
|
||||
domains running different workload types to use unintended and
|
||||
unknown ways (covert channels) to exchange some data. This way, they
|
||||
bypass the policed Xen access control mechanisms. Such
|
||||
imperfections cannot be completely eliminated and are a result of
|
||||
trade-offs between security and other design requirements. For a
|
||||
simple example of a covert channel see
|
||||
http://www.multicians.org/timing-chn.html. Such covert channels
|
||||
exist also between workloads running on different platforms if they
|
||||
are connected through networks. The Xen Chinese Wall policy provides
|
||||
an approximation of this imperfect ``air-gap'' between selected
|
||||
workload types.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Security Labels}
|
||||
|
||||
To enable Xen to associate domains with workload types running in
|
||||
them, each domain is assigned a security label that includes the
|
||||
workload types of the domain.
|
||||
|
||||
\begin{figure}
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
32 <SecurityLabelTemplate>
|
||||
33 <SubjectLabels bootstrap="SystemManagement">
|
||||
34 <VirtualMachineLabel>
|
||||
35 <Name>SystemManagement</Name>
|
||||
36 <SimpleTypeEnforcementTypes>
|
||||
37 <Type>SystemManagement</Type>
|
||||
38 <Type>PepsiCo</Type>
|
||||
39 <Type>CocaCola</Type>
|
||||
40 </SimpleTypeEnforcementTypes>
|
||||
41 <ChineseWallTypes>
|
||||
42 <Type>SystemManagement</Type>
|
||||
43 </ChineseWallTypes>
|
||||
44 </VirtualMachineLabel>
|
||||
45
|
||||
46 <VirtualMachineLabel>
|
||||
47 <Name>PepsiCo</Name>
|
||||
48 <SimpleTypeEnforcementTypes>
|
||||
49 <Type>PepsiCo</Type>
|
||||
50 </SimpleTypeEnforcementTypes>
|
||||
51 <ChineseWallTypes>
|
||||
52 <Type>PepsiCo</Type>
|
||||
53 </ChineseWallTypes>
|
||||
54 </VirtualMachineLabel>
|
||||
55
|
||||
56 <VirtualMachineLabel>
|
||||
57 <Name>CocaCola</Name>
|
||||
58 <SimpleTypeEnforcementTypes>
|
||||
59 <Type>CocaCola</Type>
|
||||
60 </SimpleTypeEnforcementTypes>
|
||||
61 <ChineseWallTypes>
|
||||
62 <Type>CocaCola</Type>
|
||||
63 </ChineseWallTypes>
|
||||
64 </VirtualMachineLabel>
|
||||
65 </SubjectLabels>
|
||||
66
|
||||
67 <ObjectLabels>
|
||||
68 <ResourceLabel>
|
||||
69 <Name>SystemManagement</Name>
|
||||
70 <SimpleTypeEnforcementTypes>
|
||||
71 <Type>SystemManagement</Type>
|
||||
72 </SimpleTypeEnforcementTypes>
|
||||
73 </ResourceLabel>
|
||||
74
|
||||
75 <ResourceLabel>
|
||||
76 <Name>PepsiCo</Name>
|
||||
77 <SimpleTypeEnforcementTypes>
|
||||
78 <Type>PepsiCo</Type>
|
||||
79 </SimpleTypeEnforcementTypes>
|
||||
80 </ResourceLabel>
|
||||
81
|
||||
82 <ResourceLabel>
|
||||
83 <Name>CocaCola</Name>
|
||||
84 <SimpleTypeEnforcementTypes>
|
||||
85 <Type>CocaCola</Type>
|
||||
86 </SimpleTypeEnforcementTypes>
|
||||
87 </ResourceLabel>
|
||||
88 </ObjectLabels>
|
||||
89 </SecurityLabelTemplate>
|
||||
90 </SecurityPolicyDefinition>
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
\caption{Example XML security policy file -- Part II: Label Definition.}
|
||||
\label{fig:acmxmlfileb}
|
||||
\end{figure}
|
||||
|
||||
Lines 32-89 (cf Figure~\ref{fig:acmxmlfileb}) define the
|
||||
\verb|SecurityLabelTemplate|, which includes the labels that can be
|
||||
attached to domains and resources when this policy is active. The
|
||||
domain labels include Chinese Wall types while resource labels do not
|
||||
include Chinese Wall types. Lines 33-65 define the
|
||||
\verb|SubjectLabels| that can be assigned to domains. For example, the
|
||||
virtual machine label \verb|CocaCola| (cf lines 56-64 in
|
||||
Figure~\ref{fig:acmxmlfileb}) associates the domain that carries it
|
||||
with the workload type \verb|CocaCola|.
|
||||
|
||||
The \verb|bootstrap| attribute names the label
|
||||
\verb|SystemManagement|. Xen will assign this label to Domain0 at
|
||||
boot time. All other domains are assigned labels according to their
|
||||
domain configuration file (see
|
||||
Section~\ref{subsection:acmexamplelabeldomains} for examples of how to
|
||||
label domains). Lines 67-88 define the \verb|ObjectLabels|. Those
|
||||
labels can be assigned to resources when this policy is active.
|
||||
|
||||
In general, user domains should be assigned labels that have only a
|
||||
single SimpleTypeEnforcement workload type. This way, workloads remain
|
||||
confined even if user domains become rogue. Any domain that is
|
||||
assigned a label with multiple STE types must be trusted to keep
|
||||
information belonging to the different STE types separate (confined).
|
||||
For example, Domain0 is assigned the bootstrap label
|
||||
\verb|SystemsManagement|, which includes all existing STE types.
|
||||
Therefore, Domain0 must take care not to enable unauthorized
|
||||
information flow (eg. through block devices or virtual networking)
|
||||
between domains or resources that are assigned different STE types.
|
||||
|
||||
Security administrators simply use the name of a label (specified in
|
||||
the \verb|<Name>| field) to associate a label with a domain (cf.
|
||||
Section~\ref{subsection:acmexamplelabeldomains}). The types inside the
|
||||
label are used by the Xen access control enforcement. While the name
|
||||
can be arbitrarily chosen (as long as it is unique), it is advisable
|
||||
to choose the label name in accordance to the security types included.
|
||||
While the XML representation in the above label seems unnecessary
|
||||
flexible, labels in general can consist of multiple types as we will
|
||||
see in the following example.
|
||||
|
||||
Assume that \verb|PepsiCo| and \verb|CocaCola| workloads use virtual
|
||||
disks that are provided by a virtual I/O domain hosting a physical
|
||||
storage device and carrying the following label:
|
||||
|
||||
\begin{scriptsize}
|
||||
\begin{verbatim}
|
||||
<VirtualMachineLabel>
|
||||
<Name>VIO</Name>
|
||||
<SimpleTypeEnforcementTypes>
|
||||
<Type>CocaCola</Type>
|
||||
<Type>PepsiCo</Type>
|
||||
</SimpleTypeEnforcementTypes>
|
||||
<ChineseWallTypes>
|
||||
<Type>VIOServer</Type>
|
||||
</ChineseWallTypes>
|
||||
</VirtualMachineLabel>
|
||||
\end{verbatim}
|
||||
\end{scriptsize}
|
||||
|
||||
This Virtual I/O domain (VIO) exports its virtualized disks by
|
||||
communicating both to domains labeled with the \verb|PepsiCo| label
|
||||
and domains labeled with the \verb|CocaCola| label. This requires the
|
||||
VIO domain to carry both the STE types \verb|CocaCola| and
|
||||
\verb|PepsiCo|. In this example, the confinement of \verb|CocaCola|
|
||||
and \verb|PepsiCo| workload depends on a VIO domain that must keep the
|
||||
data of those different workloads separate. The virtual disks are
|
||||
labeled as well (see Section~\ref{subsection:acmexamplelabelresources}
|
||||
for labeling resources) and enforcement functions inside the VIO
|
||||
domain must ensure that the labels of the domain mounting a virtual
|
||||
disk and the virtual disk label share a common STE type. The VIO label
|
||||
carrying its own VIOServer CHWALL type introduces the flexibility to
|
||||
permit the trusted VIO server to run together with CocaCola or PepsiCo
|
||||
workloads.
|
||||
|
||||
Alternatively, a system that has two hard-drives does not need a VIO
|
||||
domain but can directly assign one hardware storage device to each of
|
||||
the workloads (if the platform offers an IO-MMU, cf
|
||||
Section~\ref{s:ddsecurity}. Sharing hardware through virtualization
|
||||
is a trade-off between the amount of trusted code (size of the trusted
|
||||
computing base) and the amount of acceptable over-provisioning. This
|
||||
holds both for peripherals and for system platforms.
|
||||
|
||||
\subsection{Tools For Creating sHype/Xen Security Policies}
|
||||
To create a security policy for Xen, you can use one of the following
|
||||
tools:
|
||||
\begin{itemize}
|
||||
\item \verb|ezPolicy| GUI tool -- start writing policies
|
||||
\item \verb|xensec_gen| tool -- refine policies created with \verb|ezPolicy|
|
||||
\item text or XML editor
|
||||
\end{itemize}
|
||||
|
||||
We use the \verb|ezPolicy| tool in
|
||||
Section~\ref{subsection:acmexamplecreate} to quickly create a workload
|
||||
protection policy. If desired, the resulting XML policy file can be
|
||||
loaded into the \verb|xensec_gen| tool to refine it. It can also be
|
||||
directly edited using an XML editor. Any XML policy file is verified
|
||||
against the security policy schema when it is translated (see
|
||||
Subsection~\ref{subsection:acmexampleinstall}).
|
||||
|
||||
\section{Current Limitations}
|
||||
\label{section:acmlimitations}
|
||||
|
||||
The sHype/ACM configuration for Xen is work in progress. There is
|
||||
ongoing work for protecting virtualized resources and planned and
|
||||
ongoing work for protecting access to remote resources and domains.
|
||||
The following sections describe limitations of some of the areas into
|
||||
which access control is being extended.
|
||||
|
||||
\subsection{Network Traffic}
|
||||
Local and remote network traffic is currently not controlled.
|
||||
Solutions to add sHype/ACM policy enforcement to the virtual network
|
||||
exist but need to be discussed before they can become part of Xen.
|
||||
Subjecting external network traffic to the ACM security policy is work
|
||||
in progress. Manually setting up filters in domain 0 is required for
|
||||
now but does not scale well.
|
||||
|
||||
\subsection{Resource Access and Usage Control}
|
||||
|
||||
Enforcing the security policy across multiple hypervisor systems and
|
||||
on access to remote shared resources is work in progress. Extending
|
||||
access control to new types of resources is ongoing work (e.g. network
|
||||
storage).
|
||||
|
||||
On a single Xen system, information about the association of resources
|
||||
and security labels is stored in
|
||||
\verb|/etc/xen/acm-security/policy/resource_labels|. This file relates
|
||||
a full resource path with a security label. This association is weak
|
||||
and will break if resources are moved or renamed without adapting the
|
||||
label file. Improving the protection of label-resource relationships
|
||||
is ongoing work.
|
||||
|
||||
Controlling resource usage and enforcing resource limits in general is
|
||||
ongoing work in the Xen community.
|
||||
|
||||
\subsection{Domain Migration}
|
||||
|
||||
Labels on domains are enforced during domain migration and the
|
||||
destination hypervisor will ensure that the domain label is valid and
|
||||
the domain is permitted to run (considering the Chinese Wall policy
|
||||
rules) before it accepts the migration. However, the network between
|
||||
the source and destination hypervisor as well as both hypervisors must
|
||||
be trusted. Architectures and prototypes exist that both protect the
|
||||
network connection and ensure that the hypervisors enforce access
|
||||
control consistently but patches are not yet available for the main
|
||||
stream.
|
||||
|
||||
\subsection{Covert Channels}
|
||||
|
||||
The sHype access control aims at system independent security policies.
|
||||
It builds on top of the core hypervisor isolation. Any covert channels
|
||||
that exist in the core hypervisor or in the hardware (e.g., shared
|
||||
processor cache) will be inherited. If those covert channels are not
|
||||
the result of trade-offs between security and other system properties,
|
||||
then they are most effectively minimized or eliminated where they are
|
||||
caused. sHype offers however some means to mitigate their impact
|
||||
(cf. run-time exclusion rules).
|
||||
|
||||
\part{Reference}
|
||||
|
||||
%% Chapter Build and Boot Options
|
||||
@@ -2188,7 +3170,7 @@ editing \path{grub.conf}.
|
||||
\item [ tbuf\_size=xxx ] Set the size of the per-cpu trace buffers, in
|
||||
pages (default 0).
|
||||
\item [ sched=xxx ] Select the CPU scheduler Xen should use. The
|
||||
current possibilities are `sedf' (default), `credit', and `bvt'.
|
||||
current possibilities are `credit' (default), `sedf', and `bvt'.
|
||||
\item [ apic\_verbosity=debug,verbose ] Print more detailed
|
||||
information about local APIC and IOAPIC configuration.
|
||||
\item [ lapic ] Force use of local APIC even when left disabled by
|
||||
|
||||
@@ -53,7 +53,7 @@ int xencons_ring_send(const char *data, unsigned len)
|
||||
|
||||
|
||||
|
||||
static void handle_input(int port, struct pt_regs *regs, void *ign)
|
||||
static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign)
|
||||
{
|
||||
struct xencons_interface *intf = xencons_interface();
|
||||
XENCONS_RING_IDX cons, prod;
|
||||
|
||||
+43
-33
@@ -26,20 +26,20 @@
|
||||
|
||||
/* this represents a event handler. Chaining or sharing is not allowed */
|
||||
typedef struct _ev_action_t {
|
||||
void (*handler)(int, struct pt_regs *, void *);
|
||||
evtchn_handler_t handler;
|
||||
void *data;
|
||||
u32 count;
|
||||
} ev_action_t;
|
||||
|
||||
|
||||
static ev_action_t ev_actions[NR_EVS];
|
||||
void default_handler(int port, struct pt_regs *regs, void *data);
|
||||
void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
|
||||
|
||||
|
||||
/*
|
||||
* Demux events to different handlers.
|
||||
*/
|
||||
int do_event(u32 port, struct pt_regs *regs)
|
||||
int do_event(evtchn_port_t port, struct pt_regs *regs)
|
||||
{
|
||||
ev_action_t *action;
|
||||
if (port >= NR_EVS) {
|
||||
@@ -60,8 +60,8 @@ int do_event(u32 port, struct pt_regs *regs)
|
||||
|
||||
}
|
||||
|
||||
int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *),
|
||||
void *data )
|
||||
evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
|
||||
void *data)
|
||||
{
|
||||
if(ev_actions[port].handler != default_handler)
|
||||
printk("WARN: Handler for port %d already registered, replacing\n",
|
||||
@@ -77,7 +77,7 @@ int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *),
|
||||
return port;
|
||||
}
|
||||
|
||||
void unbind_evtchn( u32 port )
|
||||
void unbind_evtchn(evtchn_port_t port )
|
||||
{
|
||||
if (ev_actions[port].handler == default_handler)
|
||||
printk("WARN: No handler for port %d when unbinding\n", port);
|
||||
@@ -86,8 +86,7 @@ void unbind_evtchn( u32 port )
|
||||
ev_actions[port].data = NULL;
|
||||
}
|
||||
|
||||
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
|
||||
void *data)
|
||||
int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
|
||||
@@ -105,11 +104,6 @@ int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unbind_virq( u32 port )
|
||||
{
|
||||
unbind_evtchn(port);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
/* Allocate 4 pages for the irqstack */
|
||||
#define STACK_PAGES 4
|
||||
@@ -142,32 +136,48 @@ void init_events(void)
|
||||
}
|
||||
}
|
||||
|
||||
void default_handler(int port, struct pt_regs *regs, void *ignore)
|
||||
void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
|
||||
{
|
||||
printk("[Port %d] - event received\n", port);
|
||||
}
|
||||
|
||||
/* Create a port available to the pal for exchanging notifications.
|
||||
Returns the result of the hypervisor call. */
|
||||
|
||||
/* Unfortunate confusion of terminology: the port is unbound as far
|
||||
as Xen is concerned, but we automatically bind a handler to it
|
||||
from inside mini-os. */
|
||||
int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
|
||||
void *data),
|
||||
void *data)
|
||||
|
||||
int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
|
||||
void *data, evtchn_port_t *port)
|
||||
{
|
||||
u32 port;
|
||||
evtchn_op_t op;
|
||||
int err;
|
||||
|
||||
op.cmd = EVTCHNOP_alloc_unbound;
|
||||
op.u.alloc_unbound.dom = DOMID_SELF;
|
||||
op.u.alloc_unbound.remote_dom = 0;
|
||||
|
||||
err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err) {
|
||||
printk("Failed to alloc unbound evtchn: %d.\n", err);
|
||||
return -1;
|
||||
}
|
||||
port = op.u.alloc_unbound.port;
|
||||
bind_evtchn(port, handler, data);
|
||||
return port;
|
||||
evtchn_op_t op;
|
||||
op.cmd = EVTCHNOP_alloc_unbound;
|
||||
op.u.alloc_unbound.dom = DOMID_SELF;
|
||||
op.u.alloc_unbound.remote_dom = pal;
|
||||
int err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err)
|
||||
return err;
|
||||
*port = bind_evtchn(op.u.alloc_unbound.port, handler, data);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Connect to a port so as to allow the exchange of notifications with
|
||||
the pal. Returns the result of the hypervisor call. */
|
||||
|
||||
int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
|
||||
evtchn_handler_t handler, void *data,
|
||||
evtchn_port_t *local_port)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
op.cmd = EVTCHNOP_bind_interdomain;
|
||||
op.u.bind_interdomain.remote_dom = pal;
|
||||
op.u.bind_interdomain.remote_port = remote_port;
|
||||
int err = HYPERVISOR_event_channel_op(&op);
|
||||
if (err)
|
||||
return err;
|
||||
evtchn_port_t port = op.u.bind_interdomain.local_port;
|
||||
clear_evtchn(port); /* Without, handler gets invoked now! */
|
||||
*local_port = bind_evtchn(port, handler, data);
|
||||
return err;
|
||||
}
|
||||
@@ -137,6 +137,18 @@ gnttab_alloc_and_grant(void **map)
|
||||
return gref;
|
||||
}
|
||||
|
||||
static const char *gnttabop_error_msgs[] = GNTTABOP_error_msgs;
|
||||
|
||||
const char *
|
||||
gnttabop_error(int16_t status)
|
||||
{
|
||||
status = -status;
|
||||
if (status < 0 || status >= ARRAY_SIZE(gnttabop_error_msgs))
|
||||
return "bad status";
|
||||
else
|
||||
return gnttabop_error_msgs[status];
|
||||
}
|
||||
|
||||
void
|
||||
init_gnttab(void)
|
||||
{
|
||||
|
||||
@@ -22,20 +22,22 @@
|
||||
#include<traps.h>
|
||||
#include <xen/event_channel.h>
|
||||
|
||||
/* prototypes */
|
||||
int do_event(u32 port, struct pt_regs *regs);
|
||||
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
|
||||
void *data);
|
||||
int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
|
||||
void *data );
|
||||
void unbind_evtchn( u32 port );
|
||||
void init_events(void);
|
||||
void unbind_virq( u32 port );
|
||||
int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
|
||||
void *data),
|
||||
void *data);
|
||||
typedef void (*evtchn_handler_t)(evtchn_port_t, struct pt_regs *, void *);
|
||||
|
||||
static inline int notify_remote_via_evtchn(int port)
|
||||
/* prototypes */
|
||||
int do_event(evtchn_port_t port, struct pt_regs *regs);
|
||||
int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data);
|
||||
evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
|
||||
void *data);
|
||||
void unbind_evtchn(evtchn_port_t port);
|
||||
void init_events(void);
|
||||
int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
|
||||
void *data, evtchn_port_t *port);
|
||||
int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
|
||||
evtchn_handler_t handler, void *data,
|
||||
evtchn_port_t *local_port);
|
||||
|
||||
static inline int notify_remote_via_evtchn(evtchn_port_t port)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
op.cmd = EVTCHNOP_send;
|
||||
|
||||
@@ -10,5 +10,6 @@ grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame,
|
||||
grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
|
||||
unsigned long gnttab_end_transfer(grant_ref_t gref);
|
||||
int gnttab_end_access(grant_ref_t ref);
|
||||
const char *gnttabop_error(int16_t status);
|
||||
|
||||
#endif /* !__GNTTAB_H__ */
|
||||
@@ -215,7 +215,7 @@ void block_domain(u32 millisecs)
|
||||
/*
|
||||
* Just a dummy
|
||||
*/
|
||||
static void timer_handler(int ev, struct pt_regs *regs, void *ign)
|
||||
static void timer_handler(evtchn_port_t ev, struct pt_regs *regs, void *ign)
|
||||
{
|
||||
static int i;
|
||||
|
||||
|
||||
@@ -112,7 +112,8 @@ static void xenbus_thread_func(void *ign)
|
||||
}
|
||||
}
|
||||
|
||||
static void xenbus_evtchn_handler(int port, struct pt_regs *regs, void *ign)
|
||||
static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
|
||||
void *ign)
|
||||
{
|
||||
wake_up(&xb_waitq);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
|
||||
|
||||
init_MUTEX(&mm->context.sem);
|
||||
mm->context.size = 0;
|
||||
mm->context.has_foreign_mappings = 0;
|
||||
old_mm = current->mm;
|
||||
if (old_mm && old_mm->context.size > 0) {
|
||||
down(&old_mm->context.sem);
|
||||
|
||||
@@ -126,6 +126,8 @@ int direct_remap_pfn_range(struct vm_area_struct *vma,
|
||||
if (domid == DOMID_SELF)
|
||||
return -EINVAL;
|
||||
|
||||
vma->vm_mm->context.has_foreign_mappings = 1;
|
||||
|
||||
return __direct_remap_pfn_range(
|
||||
vma->vm_mm, address, mfn, size, prot, domid);
|
||||
}
|
||||
|
||||
@@ -694,6 +694,7 @@ void _arch_exit_mmap(struct mm_struct *mm)
|
||||
task_unlock(tsk);
|
||||
|
||||
if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
|
||||
(atomic_read(&mm->mm_count) == 1))
|
||||
(atomic_read(&mm->mm_count) == 1) &&
|
||||
!mm->context.has_foreign_mappings)
|
||||
mm_unpin(mm);
|
||||
}
|
||||
@@ -438,6 +438,21 @@ config PCI_DOMAINS
|
||||
bool
|
||||
default PCI
|
||||
|
||||
config XEN_PCIDEV_FRONTEND
|
||||
bool "Xen PCI Frontend"
|
||||
depends on PCI && XEN
|
||||
default y
|
||||
help
|
||||
The PCI device frontend driver allows the kernel to import arbitrary
|
||||
PCI devices from a PCI backend to support PCI driver domains.
|
||||
|
||||
config XEN_PCIDEV_FE_DEBUG
|
||||
bool "Xen PCI Frontend Debugging"
|
||||
depends on XEN_PCIDEV_FRONTEND
|
||||
default n
|
||||
help
|
||||
Enables some debug statements within the PCI Frontend.
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
|
||||
source "drivers/pci/hotplug/Kconfig"
|
||||
|
||||
@@ -159,7 +159,8 @@ void _arch_exit_mmap(struct mm_struct *mm)
|
||||
|
||||
task_unlock(tsk);
|
||||
|
||||
if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) )
|
||||
if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
|
||||
!mm->context.has_foreign_mappings )
|
||||
mm_unpin(mm);
|
||||
}
|
||||
|
||||
|
||||
@@ -143,15 +143,6 @@ config XEN_TPMDEV_BACKEND
|
||||
help
|
||||
The TPM-device backend driver
|
||||
|
||||
config XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
|
||||
bool "TPM backend closes upon vTPM failure"
|
||||
depends on XEN_TPMDEV_BACKEND
|
||||
default n
|
||||
help
|
||||
The TPM backend closes the channel if the vTPM in userspace indicates
|
||||
a failure. The corresponding domain's channel will be closed.
|
||||
Say Y if you want this feature.
|
||||
|
||||
config XEN_BLKDEV_FRONTEND
|
||||
tristate "Block-device frontend driver"
|
||||
depends on XEN
|
||||
|
||||
@@ -76,6 +76,10 @@ typedef struct netif_st {
|
||||
struct vm_struct *tx_comms_area;
|
||||
struct vm_struct *rx_comms_area;
|
||||
|
||||
/* Set of features that can be turned on in dev->features. */
|
||||
int features;
|
||||
int can_queue;
|
||||
|
||||
/* Allow netif_be_start_xmit() to peek ahead in the rx request ring. */
|
||||
RING_IDX rx_req_cons_peek;
|
||||
|
||||
@@ -86,8 +90,6 @@ typedef struct netif_st {
|
||||
struct timer_list credit_timeout;
|
||||
|
||||
/* Miscellaneous private stuff. */
|
||||
enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
|
||||
int active;
|
||||
struct list_head list; /* scheduling list */
|
||||
atomic_t refcnt;
|
||||
struct net_device *dev;
|
||||
@@ -121,4 +123,16 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev);
|
||||
struct net_device_stats *netif_be_get_stats(struct net_device *dev);
|
||||
irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs);
|
||||
|
||||
static inline int netbk_can_queue(struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
return netif->can_queue;
|
||||
}
|
||||
|
||||
static inline int netbk_can_sg(struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
return netif->features & NETIF_F_SG;
|
||||
}
|
||||
|
||||
#endif /* __NETIF__BACKEND__COMMON_H__ */
|
||||
@@ -36,46 +36,74 @@
|
||||
|
||||
static void __netif_up(netif_t *netif)
|
||||
{
|
||||
struct net_device *dev = netif->dev;
|
||||
netif_tx_lock_bh(dev);
|
||||
netif->active = 1;
|
||||
netif_tx_unlock_bh(dev);
|
||||
enable_irq(netif->irq);
|
||||
netif_schedule_work(netif);
|
||||
}
|
||||
|
||||
static void __netif_down(netif_t *netif)
|
||||
{
|
||||
struct net_device *dev = netif->dev;
|
||||
disable_irq(netif->irq);
|
||||
netif_tx_lock_bh(dev);
|
||||
netif->active = 0;
|
||||
netif_tx_unlock_bh(dev);
|
||||
netif_deschedule_work(netif);
|
||||
}
|
||||
|
||||
static int net_open(struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
if (netif->status == CONNECTED)
|
||||
if (netif_carrier_ok(dev))
|
||||
__netif_up(netif);
|
||||
netif_start_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_close(struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
netif_stop_queue(dev);
|
||||
if (netif->status == CONNECTED)
|
||||
if (netif_carrier_ok(dev))
|
||||
__netif_down(netif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netbk_change_mtu(struct net_device *dev, int mtu)
|
||||
{
|
||||
int max = netbk_can_sg(dev) ? 65535 - ETH_HLEN : ETH_DATA_LEN;
|
||||
|
||||
if (mtu > max)
|
||||
return -EINVAL;
|
||||
dev->mtu = mtu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netbk_set_sg(struct net_device *dev, u32 data)
|
||||
{
|
||||
if (data) {
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
|
||||
if (!(netif->features & NETIF_F_SG))
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return ethtool_op_set_sg(dev, data);
|
||||
}
|
||||
|
||||
static int netbk_set_tso(struct net_device *dev, u32 data)
|
||||
{
|
||||
if (data) {
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
|
||||
if (!(netif->features & NETIF_F_TSO))
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return ethtool_op_set_tso(dev, data);
|
||||
}
|
||||
|
||||
static struct ethtool_ops network_ethtool_ops =
|
||||
{
|
||||
.get_tx_csum = ethtool_op_get_tx_csum,
|
||||
.set_tx_csum = ethtool_op_set_tx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.set_sg = netbk_set_sg,
|
||||
.get_tso = ethtool_op_get_tso,
|
||||
.set_tso = netbk_set_tso,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
@@ -93,11 +121,12 @@ netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
netif = netdev_priv(dev);
|
||||
memset(netif, 0, sizeof(*netif));
|
||||
netif->domid = domid;
|
||||
netif->handle = handle;
|
||||
netif->status = DISCONNECTED;
|
||||
atomic_set(&netif->refcnt, 1);
|
||||
init_waitqueue_head(&netif->waiting_to_free);
|
||||
netif->dev = dev;
|
||||
@@ -110,12 +139,16 @@ netif_t *netif_alloc(domid_t domid, unsigned int handle, u8 be_mac[ETH_ALEN])
|
||||
dev->get_stats = netif_be_get_stats;
|
||||
dev->open = net_open;
|
||||
dev->stop = net_close;
|
||||
dev->change_mtu = netbk_change_mtu;
|
||||
dev->features = NETIF_F_IP_CSUM;
|
||||
|
||||
SET_ETHTOOL_OPS(dev, &network_ethtool_ops);
|
||||
|
||||
/* Disable queuing. */
|
||||
dev->tx_queue_len = 0;
|
||||
/*
|
||||
* Reduce default TX queuelen so that each guest interface only
|
||||
* allows it to eat around 6.4MB of host memory.
|
||||
*/
|
||||
dev->tx_queue_len = 100;
|
||||
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
if (be_mac[i] != 0)
|
||||
@@ -256,11 +289,9 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
netif->rx_req_cons_peek = 0;
|
||||
|
||||
netif_get(netif);
|
||||
wmb(); /* Other CPUs see new state before interface is started. */
|
||||
|
||||
rtnl_lock();
|
||||
netif->status = CONNECTED;
|
||||
wmb();
|
||||
netif_carrier_on(netif->dev);
|
||||
if (netif_running(netif->dev))
|
||||
__netif_up(netif);
|
||||
rtnl_unlock();
|
||||
@@ -296,20 +327,13 @@ static void netif_free(netif_t *netif)
|
||||
|
||||
void netif_disconnect(netif_t *netif)
|
||||
{
|
||||
switch (netif->status) {
|
||||
case CONNECTED:
|
||||
if (netif_carrier_ok(netif->dev)) {
|
||||
rtnl_lock();
|
||||
netif->status = DISCONNECTING;
|
||||
wmb();
|
||||
netif_carrier_off(netif->dev);
|
||||
if (netif_running(netif->dev))
|
||||
__netif_down(netif);
|
||||
rtnl_unlock();
|
||||
netif_put(netif);
|
||||
/* fall through */
|
||||
case DISCONNECTED:
|
||||
netif_free(netif);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
netif_free(netif);
|
||||
}
|
||||
@@ -40,17 +40,22 @@
|
||||
|
||||
/*#define NETBE_DEBUG_INTERRUPT*/
|
||||
|
||||
struct netbk_rx_meta {
|
||||
skb_frag_t frag;
|
||||
int id;
|
||||
};
|
||||
|
||||
static void netif_idx_release(u16 pending_idx);
|
||||
static void netif_page_release(struct page *page);
|
||||
static void make_tx_response(netif_t *netif,
|
||||
netif_tx_request_t *txp,
|
||||
s8 st);
|
||||
static int make_rx_response(netif_t *netif,
|
||||
u16 id,
|
||||
s8 st,
|
||||
u16 offset,
|
||||
u16 size,
|
||||
u16 flags);
|
||||
static netif_rx_response_t *make_rx_response(netif_t *netif,
|
||||
u16 id,
|
||||
s8 st,
|
||||
u16 offset,
|
||||
u16 size,
|
||||
u16 flags);
|
||||
|
||||
static void net_tx_action(unsigned long unused);
|
||||
static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0);
|
||||
@@ -100,21 +105,27 @@ static spinlock_t net_schedule_list_lock;
|
||||
static unsigned long mfn_list[MAX_MFN_ALLOC];
|
||||
static unsigned int alloc_index = 0;
|
||||
|
||||
static unsigned long alloc_mfn(void)
|
||||
static inline unsigned long alloc_mfn(void)
|
||||
{
|
||||
return mfn_list[--alloc_index];
|
||||
}
|
||||
|
||||
static int check_mfn(int nr)
|
||||
{
|
||||
unsigned long mfn = 0;
|
||||
struct xen_memory_reservation reservation = {
|
||||
.nr_extents = MAX_MFN_ALLOC,
|
||||
.extent_order = 0,
|
||||
.domid = DOMID_SELF
|
||||
};
|
||||
set_xen_guest_handle(reservation.extent_start, mfn_list);
|
||||
if ( unlikely(alloc_index == 0) )
|
||||
alloc_index = HYPERVISOR_memory_op(
|
||||
XENMEM_increase_reservation, &reservation);
|
||||
if ( alloc_index != 0 )
|
||||
mfn = mfn_list[--alloc_index];
|
||||
return mfn;
|
||||
|
||||
if (likely(alloc_index >= nr))
|
||||
return 0;
|
||||
|
||||
set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index);
|
||||
reservation.nr_extents = MAX_MFN_ALLOC - alloc_index;
|
||||
alloc_index += HYPERVISOR_memory_op(XENMEM_increase_reservation,
|
||||
&reservation);
|
||||
|
||||
return alloc_index >= nr ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static inline void maybe_schedule_tx_action(void)
|
||||
@@ -136,6 +147,96 @@ static inline int is_xen_skb(struct sk_buff *skb)
|
||||
return (cp == skbuff_cachep);
|
||||
}
|
||||
|
||||
static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct skb_shared_info *ninfo;
|
||||
struct sk_buff *nskb;
|
||||
unsigned long offset;
|
||||
int ret;
|
||||
int len;
|
||||
int headlen;
|
||||
|
||||
nskb = alloc_skb(SKB_MAX_HEAD(0), GFP_ATOMIC);
|
||||
if (unlikely(!nskb))
|
||||
goto err;
|
||||
|
||||
skb_reserve(nskb, 16);
|
||||
headlen = nskb->end - nskb->data;
|
||||
if (headlen > skb_headlen(skb))
|
||||
headlen = skb_headlen(skb);
|
||||
ret = skb_copy_bits(skb, 0, __skb_put(nskb, headlen), headlen);
|
||||
BUG_ON(ret);
|
||||
|
||||
ninfo = skb_shinfo(nskb);
|
||||
ninfo->gso_size = skb_shinfo(skb)->gso_size;
|
||||
ninfo->gso_type = skb_shinfo(skb)->gso_type;
|
||||
|
||||
offset = headlen;
|
||||
len = skb->len - headlen;
|
||||
|
||||
nskb->len = skb->len;
|
||||
nskb->data_len = len;
|
||||
nskb->truesize += len;
|
||||
|
||||
while (len) {
|
||||
struct page *page;
|
||||
int copy;
|
||||
int zero;
|
||||
|
||||
if (unlikely(ninfo->nr_frags >= MAX_SKB_FRAGS)) {
|
||||
dump_stack();
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
copy = len >= PAGE_SIZE ? PAGE_SIZE : len;
|
||||
zero = len >= PAGE_SIZE ? 0 : __GFP_ZERO;
|
||||
|
||||
page = alloc_page(GFP_ATOMIC | zero);
|
||||
if (unlikely(!page))
|
||||
goto err_free;
|
||||
|
||||
ret = skb_copy_bits(skb, offset, page_address(page), copy);
|
||||
BUG_ON(ret);
|
||||
|
||||
ninfo->frags[ninfo->nr_frags].page = page;
|
||||
ninfo->frags[ninfo->nr_frags].page_offset = 0;
|
||||
ninfo->frags[ninfo->nr_frags].size = copy;
|
||||
ninfo->nr_frags++;
|
||||
|
||||
offset += copy;
|
||||
len -= copy;
|
||||
}
|
||||
|
||||
offset = nskb->data - skb->data;
|
||||
|
||||
nskb->h.raw = skb->h.raw + offset;
|
||||
nskb->nh.raw = skb->nh.raw + offset;
|
||||
nskb->mac.raw = skb->mac.raw + offset;
|
||||
|
||||
return nskb;
|
||||
|
||||
err_free:
|
||||
kfree_skb(nskb);
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int netbk_max_required_rx_slots(netif_t *netif)
|
||||
{
|
||||
if (netif->features & (NETIF_F_SG|NETIF_F_TSO))
|
||||
return MAX_SKB_FRAGS + 2; /* header + extra_info + frags */
|
||||
return 1; /* all in one */
|
||||
}
|
||||
|
||||
static inline int netbk_queue_full(netif_t *netif)
|
||||
{
|
||||
RING_IDX peek = netif->rx_req_cons_peek;
|
||||
RING_IDX needed = netbk_max_required_rx_slots(netif);
|
||||
|
||||
return ((netif->rx.sring->req_prod - peek) < needed) ||
|
||||
((netif->rx.rsp_prod_pvt + NET_RX_RING_SIZE - peek) < needed);
|
||||
}
|
||||
|
||||
int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
netif_t *netif = netdev_priv(dev);
|
||||
@@ -143,30 +244,26 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
BUG_ON(skb->dev != dev);
|
||||
|
||||
/* Drop the packet if the target domain has no receive buffers. */
|
||||
if (!netif->active ||
|
||||
(netif->rx_req_cons_peek == netif->rx.sring->req_prod) ||
|
||||
((netif->rx_req_cons_peek - netif->rx.rsp_prod_pvt) ==
|
||||
NET_RX_RING_SIZE))
|
||||
if (unlikely(!netif_running(dev) || !netif_carrier_ok(dev)))
|
||||
goto drop;
|
||||
|
||||
if (unlikely(netbk_queue_full(netif))) {
|
||||
/* Not a BUG_ON() -- misbehaving netfront can trigger this. */
|
||||
if (netbk_can_queue(dev))
|
||||
DPRINTK("Queue full but not stopped!\n");
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not copy the packet unless:
|
||||
* 1. The data is shared; or
|
||||
* 2. The data is not allocated from our special cache.
|
||||
* NB. We also couldn't cope with fragmented packets, but we won't get
|
||||
* any because we not advertise the NETIF_F_SG feature.
|
||||
* 3. The data is fragmented.
|
||||
*/
|
||||
if (skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb)) {
|
||||
int hlen = skb->data - skb->head;
|
||||
int ret;
|
||||
struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
|
||||
if (skb_cloned(skb) || skb_is_nonlinear(skb) || !is_xen_skb(skb)) {
|
||||
struct sk_buff *nskb = netbk_copy_skb(skb);
|
||||
if ( unlikely(nskb == NULL) )
|
||||
goto drop;
|
||||
skb_reserve(nskb, hlen);
|
||||
__skb_put(nskb, skb->len);
|
||||
ret = skb_copy_bits(skb, -hlen, nskb->data - hlen,
|
||||
skb->len + hlen);
|
||||
BUG_ON(ret);
|
||||
/* Copy only the header fields we use in this driver. */
|
||||
nskb->dev = skb->dev;
|
||||
nskb->ip_summed = skb->ip_summed;
|
||||
@@ -175,9 +272,18 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
skb = nskb;
|
||||
}
|
||||
|
||||
netif->rx_req_cons_peek++;
|
||||
netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 +
|
||||
!!skb_shinfo(skb)->gso_size;
|
||||
netif_get(netif);
|
||||
|
||||
if (netbk_can_queue(dev) && netbk_queue_full(netif)) {
|
||||
netif->rx.sring->req_event = netif->rx_req_cons_peek +
|
||||
netbk_max_required_rx_slots(netif);
|
||||
mb(); /* request notification /then/ check & stop the queue */
|
||||
if (netbk_queue_full(netif))
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
|
||||
skb_queue_tail(&rx_queue, skb);
|
||||
tasklet_schedule(&net_rx_tasklet);
|
||||
|
||||
@@ -208,116 +314,85 @@ int xen_network_done(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void net_rx_action(unsigned long unused)
|
||||
static u16 netbk_gop_frag(netif_t *netif, struct page *page, int count, int i)
|
||||
{
|
||||
netif_t *netif = NULL;
|
||||
s8 status;
|
||||
u16 size, id, irq, flags;
|
||||
multicall_entry_t *mcl;
|
||||
mmu_update_t *mmu;
|
||||
gnttab_transfer_t *gop;
|
||||
unsigned long vdata, old_mfn, new_mfn;
|
||||
struct sk_buff_head rxq;
|
||||
struct sk_buff *skb;
|
||||
int notify_nr = 0;
|
||||
int ret;
|
||||
/*
|
||||
* Putting hundreds of bytes on the stack is considered rude.
|
||||
* Static works because a tasklet can only be on one CPU at any time.
|
||||
*/
|
||||
static u16 notify_list[NET_RX_RING_SIZE];
|
||||
multicall_entry_t *mcl = rx_mcl + count;
|
||||
mmu_update_t *mmu = rx_mmu + count;
|
||||
gnttab_transfer_t *gop = grant_rx_op + count;
|
||||
netif_rx_request_t *req;
|
||||
unsigned long old_mfn, new_mfn;
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
mcl = rx_mcl;
|
||||
mmu = rx_mmu;
|
||||
gop = grant_rx_op;
|
||||
|
||||
while ((skb = skb_dequeue(&rx_queue)) != NULL) {
|
||||
netif = netdev_priv(skb->dev);
|
||||
vdata = (unsigned long)skb->data;
|
||||
old_mfn = virt_to_mfn(vdata);
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
/* Memory squeeze? Back off for an arbitrary while. */
|
||||
if ((new_mfn = alloc_mfn()) == 0) {
|
||||
if ( net_ratelimit() )
|
||||
WPRINTK("Memory squeeze in netback "
|
||||
"driver.\n");
|
||||
mod_timer(&net_timer, jiffies + HZ);
|
||||
skb_queue_head(&rx_queue, skb);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Set the new P2M table entry before reassigning
|
||||
* the old data page. Heed the comment in
|
||||
* pgtable-2level.h:pte_page(). :-)
|
||||
*/
|
||||
set_phys_to_machine(
|
||||
__pa(skb->data) >> PAGE_SHIFT,
|
||||
new_mfn);
|
||||
|
||||
MULTI_update_va_mapping(mcl, vdata,
|
||||
pfn_pte_ma(new_mfn,
|
||||
PAGE_KERNEL), 0);
|
||||
mcl++;
|
||||
|
||||
mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = __pa(vdata) >> PAGE_SHIFT;
|
||||
mmu++;
|
||||
}
|
||||
|
||||
gop->mfn = old_mfn;
|
||||
gop->domid = netif->domid;
|
||||
gop->ref = RING_GET_REQUEST(
|
||||
&netif->rx, netif->rx.req_cons)->gref;
|
||||
netif->rx.req_cons++;
|
||||
gop++;
|
||||
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
|
||||
/* Filled the batch queue? */
|
||||
if ((gop - grant_rx_op) == ARRAY_SIZE(grant_rx_op))
|
||||
break;
|
||||
}
|
||||
old_mfn = virt_to_mfn(page_address(page));
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
if (mcl == rx_mcl)
|
||||
return;
|
||||
new_mfn = alloc_mfn();
|
||||
|
||||
mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
|
||||
/*
|
||||
* Set the new P2M table entry before reassigning
|
||||
* the old data page. Heed the comment in
|
||||
* pgtable-2level.h:pte_page(). :-)
|
||||
*/
|
||||
set_phys_to_machine(page_to_pfn(page), new_mfn);
|
||||
|
||||
if (mmu - rx_mmu) {
|
||||
mcl->op = __HYPERVISOR_mmu_update;
|
||||
mcl->args[0] = (unsigned long)rx_mmu;
|
||||
mcl->args[1] = mmu - rx_mmu;
|
||||
mcl->args[2] = 0;
|
||||
mcl->args[3] = DOMID_SELF;
|
||||
mcl++;
|
||||
}
|
||||
MULTI_update_va_mapping(mcl, (unsigned long)page_address(page),
|
||||
pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
|
||||
|
||||
ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
BUG_ON(ret != 0);
|
||||
mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = page_to_pfn(page);
|
||||
}
|
||||
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
|
||||
gop - grant_rx_op);
|
||||
BUG_ON(ret != 0);
|
||||
req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i);
|
||||
gop->mfn = old_mfn;
|
||||
gop->domid = netif->domid;
|
||||
gop->ref = req->gref;
|
||||
return req->id;
|
||||
}
|
||||
|
||||
mcl = rx_mcl;
|
||||
gop = grant_rx_op;
|
||||
while ((skb = __skb_dequeue(&rxq)) != NULL) {
|
||||
netif = netdev_priv(skb->dev);
|
||||
size = skb->tail - skb->data;
|
||||
static void netbk_gop_skb(struct sk_buff *skb, struct netbk_rx_meta *meta,
|
||||
int count)
|
||||
{
|
||||
netif_t *netif = netdev_priv(skb->dev);
|
||||
int nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
int i;
|
||||
int extra;
|
||||
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
meta[count].frag.page_offset = skb_shinfo(skb)->gso_type;
|
||||
meta[count].frag.size = skb_shinfo(skb)->gso_size;
|
||||
extra = !!meta[count].frag.size + 1;
|
||||
|
||||
netif->stats.tx_bytes += size;
|
||||
netif->stats.tx_packets++;
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
meta[++count].frag = skb_shinfo(skb)->frags[i];
|
||||
meta[count].id = netbk_gop_frag(netif, meta[count].frag.page,
|
||||
count, i + extra);
|
||||
}
|
||||
|
||||
/*
|
||||
* This must occur at the end to ensure that we don't trash
|
||||
* skb_shinfo until we're done.
|
||||
*/
|
||||
meta[count - nr_frags].id = netbk_gop_frag(netif,
|
||||
virt_to_page(skb->data),
|
||||
count - nr_frags, 0);
|
||||
netif->rx.req_cons += nr_frags + extra;
|
||||
}
|
||||
|
||||
static inline void netbk_free_pages(int nr_frags, struct netbk_rx_meta *meta)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_frags; i++)
|
||||
put_page(meta[i].frag.page);
|
||||
}
|
||||
|
||||
static int netbk_check_gop(int nr_frags, domid_t domid, int count)
|
||||
{
|
||||
multicall_entry_t *mcl = rx_mcl + count;
|
||||
gnttab_transfer_t *gop = grant_rx_op + count;
|
||||
int status = NETIF_RSP_OKAY;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= nr_frags; i++) {
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
/* The update_va_mapping() must not fail. */
|
||||
BUG_ON(mcl->result != 0);
|
||||
@@ -325,10 +400,9 @@ static void net_rx_action(unsigned long unused)
|
||||
}
|
||||
|
||||
/* Check the reassignment error code. */
|
||||
status = NETIF_RSP_OKAY;
|
||||
if (gop->status != 0) {
|
||||
DPRINTK("Bad status %d from grant transfer to DOM%u\n",
|
||||
gop->status, netif->domid);
|
||||
gop->status, domid);
|
||||
/*
|
||||
* Page no longer belongs to us unless GNTST_bad_page,
|
||||
* but that should be a fatal error anyway.
|
||||
@@ -336,24 +410,166 @@ static void net_rx_action(unsigned long unused)
|
||||
BUG_ON(gop->status == GNTST_bad_page);
|
||||
status = NETIF_RSP_ERROR;
|
||||
}
|
||||
irq = netif->irq;
|
||||
id = RING_GET_REQUEST(&netif->rx, netif->rx.rsp_prod_pvt)->id;
|
||||
flags = 0;
|
||||
gop++;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void netbk_add_frag_responses(netif_t *netif, int status,
|
||||
struct netbk_rx_meta *meta, int nr_frags)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
int id = meta[i].id;
|
||||
int flags = (i == nr_frags - 1) ? 0 : NETRXF_more_data;
|
||||
|
||||
make_rx_response(netif, id, status, meta[i].frag.page_offset,
|
||||
meta[i].frag.size, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void net_rx_action(unsigned long unused)
|
||||
{
|
||||
netif_t *netif = NULL;
|
||||
s8 status;
|
||||
u16 id, irq, flags;
|
||||
netif_rx_response_t *resp;
|
||||
struct netif_extra_info *extra;
|
||||
multicall_entry_t *mcl;
|
||||
struct sk_buff_head rxq;
|
||||
struct sk_buff *skb;
|
||||
int notify_nr = 0;
|
||||
int ret;
|
||||
int nr_frags;
|
||||
int count;
|
||||
|
||||
/*
|
||||
* Putting hundreds of bytes on the stack is considered rude.
|
||||
* Static works because a tasklet can only be on one CPU at any time.
|
||||
*/
|
||||
static u16 notify_list[NET_RX_RING_SIZE];
|
||||
static struct netbk_rx_meta meta[NET_RX_RING_SIZE];
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
count = 0;
|
||||
|
||||
while ((skb = skb_dequeue(&rx_queue)) != NULL) {
|
||||
nr_frags = skb_shinfo(skb)->nr_frags;
|
||||
*(int *)skb->cb = nr_frags;
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap) &&
|
||||
check_mfn(nr_frags + 1)) {
|
||||
/* Memory squeeze? Back off for an arbitrary while. */
|
||||
if ( net_ratelimit() )
|
||||
WPRINTK("Memory squeeze in netback "
|
||||
"driver.\n");
|
||||
mod_timer(&net_timer, jiffies + HZ);
|
||||
skb_queue_head(&rx_queue, skb);
|
||||
break;
|
||||
}
|
||||
|
||||
netbk_gop_skb(skb, meta, count);
|
||||
|
||||
count += nr_frags + 1;
|
||||
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
|
||||
/* Filled the batch queue? */
|
||||
if (count + MAX_SKB_FRAGS >= NET_RX_RING_SIZE)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
mcl = rx_mcl + count;
|
||||
|
||||
mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
|
||||
|
||||
mcl->op = __HYPERVISOR_mmu_update;
|
||||
mcl->args[0] = (unsigned long)rx_mmu;
|
||||
mcl->args[1] = count;
|
||||
mcl->args[2] = 0;
|
||||
mcl->args[3] = DOMID_SELF;
|
||||
|
||||
ret = HYPERVISOR_multicall(rx_mcl, count + 1);
|
||||
BUG_ON(ret != 0);
|
||||
}
|
||||
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op, count);
|
||||
BUG_ON(ret != 0);
|
||||
|
||||
count = 0;
|
||||
while ((skb = __skb_dequeue(&rxq)) != NULL) {
|
||||
nr_frags = *(int *)skb->cb;
|
||||
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
|
||||
netif = netdev_priv(skb->dev);
|
||||
netif->stats.tx_bytes += skb->len;
|
||||
netif->stats.tx_packets++;
|
||||
|
||||
netbk_free_pages(nr_frags, meta + count + 1);
|
||||
status = netbk_check_gop(nr_frags, netif->domid, count);
|
||||
|
||||
id = meta[count].id;
|
||||
flags = nr_frags ? NETRXF_more_data : 0;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
|
||||
flags |= NETRXF_csum_blank | NETRXF_data_validated;
|
||||
else if (skb->proto_data_valid) /* remote but checksummed? */
|
||||
flags |= NETRXF_data_validated;
|
||||
if (make_rx_response(netif, id, status,
|
||||
(unsigned long)skb->data & ~PAGE_MASK,
|
||||
size, flags) &&
|
||||
(rx_notify[irq] == 0)) {
|
||||
|
||||
resp = make_rx_response(netif, id, status,
|
||||
offset_in_page(skb->data),
|
||||
skb_headlen(skb), flags);
|
||||
|
||||
extra = NULL;
|
||||
|
||||
if (meta[count].frag.size) {
|
||||
struct netif_extra_info *gso =
|
||||
(struct netif_extra_info *)
|
||||
RING_GET_RESPONSE(&netif->rx,
|
||||
netif->rx.rsp_prod_pvt++);
|
||||
|
||||
if (extra)
|
||||
extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
|
||||
else
|
||||
resp->flags |= NETRXF_extra_info;
|
||||
|
||||
gso->u.gso.size = meta[count].frag.size;
|
||||
gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
|
||||
gso->u.gso.pad = 0;
|
||||
gso->u.gso.features = 0;
|
||||
|
||||
gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
|
||||
gso->flags = 0;
|
||||
extra = gso;
|
||||
}
|
||||
|
||||
netbk_add_frag_responses(netif, status, meta + count + 1,
|
||||
nr_frags);
|
||||
|
||||
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret);
|
||||
irq = netif->irq;
|
||||
if (ret && !rx_notify[irq]) {
|
||||
rx_notify[irq] = 1;
|
||||
notify_list[notify_nr++] = irq;
|
||||
}
|
||||
|
||||
if (netif_queue_stopped(netif->dev) &&
|
||||
!netbk_queue_full(netif))
|
||||
netif_wake_queue(netif->dev);
|
||||
|
||||
netif_put(netif);
|
||||
dev_kfree_skb(skb);
|
||||
gop++;
|
||||
count += nr_frags + 1;
|
||||
}
|
||||
|
||||
while (notify_nr != 0) {
|
||||
@@ -404,7 +620,9 @@ static void add_to_net_schedule_list_tail(netif_t *netif)
|
||||
return;
|
||||
|
||||
spin_lock_irq(&net_schedule_list_lock);
|
||||
if (!__on_net_schedule_list(netif) && netif->active) {
|
||||
if (!__on_net_schedule_list(netif) &&
|
||||
likely(netif_running(netif->dev) &&
|
||||
netif_carrier_ok(netif->dev))) {
|
||||
list_add_tail(&netif->list, &net_schedule_list);
|
||||
netif_get(netif);
|
||||
}
|
||||
@@ -972,8 +1190,13 @@ static void netif_page_release(struct page *page)
|
||||
irqreturn_t netif_be_int(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
netif_t *netif = dev_id;
|
||||
|
||||
add_to_net_schedule_list_tail(netif);
|
||||
maybe_schedule_tx_action();
|
||||
|
||||
if (netif_queue_stopped(netif->dev) && !netbk_queue_full(netif))
|
||||
netif_wake_queue(netif->dev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1007,16 +1230,15 @@ static void make_tx_response(netif_t *netif,
|
||||
#endif
|
||||
}
|
||||
|
||||
static int make_rx_response(netif_t *netif,
|
||||
u16 id,
|
||||
s8 st,
|
||||
u16 offset,
|
||||
u16 size,
|
||||
u16 flags)
|
||||
static netif_rx_response_t *make_rx_response(netif_t *netif,
|
||||
u16 id,
|
||||
s8 st,
|
||||
u16 offset,
|
||||
u16 size,
|
||||
u16 flags)
|
||||
{
|
||||
RING_IDX i = netif->rx.rsp_prod_pvt;
|
||||
netif_rx_response_t *resp;
|
||||
int notify;
|
||||
|
||||
resp = RING_GET_RESPONSE(&netif->rx, i);
|
||||
resp->offset = offset;
|
||||
@@ -1027,9 +1249,8 @@ static int make_rx_response(netif_t *netif,
|
||||
resp->status = (s16)st;
|
||||
|
||||
netif->rx.rsp_prod_pvt = ++i;
|
||||
RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, notify);
|
||||
|
||||
return notify;
|
||||
return resp;
|
||||
}
|
||||
|
||||
#ifdef NETBE_DEBUG_INTERRUPT
|
||||
|
||||
@@ -101,14 +101,12 @@ static int netback_probe(struct xenbus_device *dev,
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
#if 0 /* KAF: After the protocol is finalised. */
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
|
||||
"%d", 1);
|
||||
if (err) {
|
||||
message = "writing feature-gso-tcpv4";
|
||||
goto abort_transaction;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
} while (err == -EAGAIN);
|
||||
@@ -353,6 +351,7 @@ static int connect_rings(struct backend_info *be)
|
||||
unsigned long tx_ring_ref, rx_ring_ref;
|
||||
unsigned int evtchn;
|
||||
int err;
|
||||
int val;
|
||||
|
||||
DPRINTK("");
|
||||
|
||||
@@ -367,6 +366,30 @@ static int connect_rings(struct backend_info *be)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-rx-notify", "%d",
|
||||
&val) < 0)
|
||||
val = 0;
|
||||
if (val)
|
||||
be->netif->can_queue = 1;
|
||||
else
|
||||
/* Must be non-zero for pfifo_fast to work. */
|
||||
be->netif->dev->tx_queue_len = 1;
|
||||
|
||||
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg", "%d", &val) < 0)
|
||||
val = 0;
|
||||
if (val) {
|
||||
be->netif->features |= NETIF_F_SG;
|
||||
be->netif->dev->features |= NETIF_F_SG;
|
||||
}
|
||||
|
||||
if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4", "%d",
|
||||
&val) < 0)
|
||||
val = 0;
|
||||
if (val) {
|
||||
be->netif->features |= NETIF_F_TSO;
|
||||
be->netif->dev->features |= NETIF_F_TSO;
|
||||
}
|
||||
|
||||
/* Map the shared frame, irq etc. */
|
||||
err = netif_map(be->netif, tx_ring_ref, rx_ring_ref, evtchn);
|
||||
if (err) {
|
||||
|
||||
@@ -46,11 +46,11 @@
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/io.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/arp.h>
|
||||
#include <net/route.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <xen/evtchn.h>
|
||||
#include <xen/xenbus.h>
|
||||
@@ -62,18 +62,13 @@
|
||||
#include <xen/interface/grant_table.h>
|
||||
#include <xen/gnttab.h>
|
||||
|
||||
#define RX_COPY_THRESHOLD 256
|
||||
|
||||
#define GRANT_INVALID_REF 0
|
||||
|
||||
#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
|
||||
#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
|
||||
|
||||
static inline void init_skb_shinfo(struct sk_buff *skb)
|
||||
{
|
||||
atomic_set(&(skb_shinfo(skb)->dataref), 1);
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
skb_shinfo(skb)->frag_list = NULL;
|
||||
}
|
||||
|
||||
struct netfront_info {
|
||||
struct list_head list;
|
||||
struct net_device *netdev;
|
||||
@@ -99,17 +94,17 @@ struct netfront_info {
|
||||
struct timer_list rx_refill_timer;
|
||||
|
||||
/*
|
||||
* {tx,rx}_skbs store outstanding skbuffs. The first entry in each
|
||||
* array is an index into a chain of free entries.
|
||||
* {tx,rx}_skbs store outstanding skbuffs. The first entry in tx_skbs
|
||||
* is an index into a chain of free entries.
|
||||
*/
|
||||
struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
|
||||
struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1];
|
||||
struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
|
||||
|
||||
#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
|
||||
grant_ref_t gref_tx_head;
|
||||
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
|
||||
grant_ref_t gref_rx_head;
|
||||
grant_ref_t grant_rx_ref[NET_TX_RING_SIZE + 1];
|
||||
grant_ref_t grant_rx_ref[NET_TX_RING_SIZE];
|
||||
|
||||
struct xenbus_device *xbdev;
|
||||
int tx_ring_ref;
|
||||
@@ -121,8 +116,13 @@ struct netfront_info {
|
||||
struct mmu_update rx_mmu[NET_RX_RING_SIZE];
|
||||
};
|
||||
|
||||
struct netfront_rx_info {
|
||||
struct netif_rx_response rx;
|
||||
struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
|
||||
};
|
||||
|
||||
/*
|
||||
* Access macros for acquiring freeing slots in {tx,rx}_skbs[].
|
||||
* Access macros for acquiring freeing slots in tx_skbs[].
|
||||
*/
|
||||
|
||||
static inline void add_id_to_freelist(struct sk_buff **list, unsigned short id)
|
||||
@@ -138,6 +138,29 @@ static inline unsigned short get_id_from_freelist(struct sk_buff **list)
|
||||
return id;
|
||||
}
|
||||
|
||||
static inline int xennet_rxidx(RING_IDX idx)
|
||||
{
|
||||
return idx & (NET_RX_RING_SIZE - 1);
|
||||
}
|
||||
|
||||
static inline struct sk_buff *xennet_get_rx_skb(struct netfront_info *np,
|
||||
RING_IDX ri)
|
||||
{
|
||||
int i = xennet_rxidx(ri);
|
||||
struct sk_buff *skb = np->rx_skbs[i];
|
||||
np->rx_skbs[i] = NULL;
|
||||
return skb;
|
||||
}
|
||||
|
||||
static inline grant_ref_t xennet_get_rx_ref(struct netfront_info *np,
|
||||
RING_IDX ri)
|
||||
{
|
||||
int i = xennet_rxidx(ri);
|
||||
grant_ref_t ref = np->grant_rx_ref[i];
|
||||
np->grant_rx_ref[i] = GRANT_INVALID_REF;
|
||||
return ref;
|
||||
}
|
||||
|
||||
#define DPRINTK(fmt, args...) \
|
||||
pr_debug("netfront (%s:%d) " fmt, \
|
||||
__FUNCTION__, __LINE__, ##args)
|
||||
@@ -303,6 +326,24 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-rx-notify", "%d", 1);
|
||||
if (err) {
|
||||
message = "writing feature-rx-notify";
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1);
|
||||
if (err) {
|
||||
message = "writing feature-sg";
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", "%d", 1);
|
||||
if (err) {
|
||||
message = "writing feature-gso-tcpv4";
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err) {
|
||||
if (err == -EAGAIN)
|
||||
@@ -456,6 +497,9 @@ static int network_open(struct net_device *dev)
|
||||
network_alloc_rx_buffers(dev);
|
||||
np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
|
||||
|
||||
if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
|
||||
netif_rx_schedule(dev);
|
||||
|
||||
netif_start_queue(dev);
|
||||
|
||||
return 0;
|
||||
@@ -546,10 +590,13 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
unsigned short id;
|
||||
struct netfront_info *np = netdev_priv(dev);
|
||||
struct sk_buff *skb;
|
||||
int i, batch_target;
|
||||
struct page *page;
|
||||
int i, batch_target, notify;
|
||||
RING_IDX req_prod = np->rx.req_prod_pvt;
|
||||
struct xen_memory_reservation reservation;
|
||||
grant_ref_t ref;
|
||||
unsigned long pfn;
|
||||
void *vaddr;
|
||||
|
||||
if (unlikely(!netif_carrier_ok(dev)))
|
||||
return;
|
||||
@@ -562,29 +609,36 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
*/
|
||||
batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
|
||||
for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
|
||||
/*
|
||||
* Subtract dev_alloc_skb headroom (16 bytes) and shared info
|
||||
* tailroom then round down to SKB_DATA_ALIGN boundary.
|
||||
*/
|
||||
skb = __dev_alloc_skb(
|
||||
((PAGE_SIZE - sizeof(struct skb_shared_info)) &
|
||||
(-SKB_DATA_ALIGN(1))) - 16,
|
||||
GFP_ATOMIC|__GFP_NOWARN);
|
||||
if (skb == NULL) {
|
||||
/* Allocate an skb and a page. */
|
||||
skb = __dev_alloc_skb(RX_COPY_THRESHOLD,
|
||||
GFP_ATOMIC | __GFP_NOWARN);
|
||||
if (unlikely(!skb))
|
||||
goto no_skb;
|
||||
|
||||
page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
|
||||
if (!page) {
|
||||
kfree_skb(skb);
|
||||
no_skb:
|
||||
/* Any skbuffs queued for refill? Force them out. */
|
||||
if (i != 0)
|
||||
goto refill;
|
||||
/* Could not allocate any skbuffs. Try again later. */
|
||||
mod_timer(&np->rx_refill_timer,
|
||||
jiffies + (HZ/10));
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
skb_shinfo(skb)->frags[0].page = page;
|
||||
skb_shinfo(skb)->nr_frags = 1;
|
||||
__skb_queue_tail(&np->rx_batch, skb);
|
||||
}
|
||||
|
||||
/* Is the batch large enough to be worthwhile? */
|
||||
if (i < (np->rx_target/2))
|
||||
if (i < (np->rx_target/2)) {
|
||||
if (req_prod > np->rx.sring->req_prod)
|
||||
goto push;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Adjust our fill target if we risked running out of buffers. */
|
||||
if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
|
||||
@@ -598,26 +652,29 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
|
||||
skb->dev = dev;
|
||||
|
||||
id = get_id_from_freelist(np->rx_skbs);
|
||||
id = xennet_rxidx(req_prod + i);
|
||||
|
||||
BUG_ON(np->rx_skbs[id]);
|
||||
np->rx_skbs[id] = skb;
|
||||
|
||||
RING_GET_REQUEST(&np->rx, req_prod + i)->id = id;
|
||||
ref = gnttab_claim_grant_reference(&np->gref_rx_head);
|
||||
BUG_ON((signed short)ref < 0);
|
||||
np->grant_rx_ref[id] = ref;
|
||||
|
||||
pfn = page_to_pfn(skb_shinfo(skb)->frags[0].page);
|
||||
vaddr = page_address(skb_shinfo(skb)->frags[0].page);
|
||||
|
||||
gnttab_grant_foreign_transfer_ref(ref,
|
||||
np->xbdev->otherend_id,
|
||||
__pa(skb->head)>>PAGE_SHIFT);
|
||||
np->xbdev->otherend_id, pfn);
|
||||
RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref;
|
||||
np->rx_pfn_array[i] = virt_to_mfn(skb->head);
|
||||
np->rx_pfn_array[i] = pfn_to_mfn(pfn);
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
/* Remove this page before passing back to Xen. */
|
||||
set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
|
||||
INVALID_P2M_ENTRY);
|
||||
set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
|
||||
MULTI_update_va_mapping(np->rx_mcl+i,
|
||||
(unsigned long)skb->head,
|
||||
(unsigned long)vaddr,
|
||||
__pte(0), 0);
|
||||
}
|
||||
}
|
||||
@@ -654,7 +711,10 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
|
||||
/* Above is a suitable barrier to ensure backend will see requests. */
|
||||
np->rx.req_prod_pvt = req_prod + i;
|
||||
RING_PUSH_REQUESTS(&np->rx);
|
||||
push:
|
||||
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
|
||||
if (notify)
|
||||
notify_remote_via_irq(np->irq);
|
||||
}
|
||||
|
||||
static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
|
||||
@@ -840,20 +900,232 @@ static irqreturn_t netif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void xennet_move_rx_slot(struct netfront_info *np, struct sk_buff *skb,
|
||||
grant_ref_t ref)
|
||||
{
|
||||
int new = xennet_rxidx(np->rx.req_prod_pvt);
|
||||
|
||||
BUG_ON(np->rx_skbs[new]);
|
||||
np->rx_skbs[new] = skb;
|
||||
np->grant_rx_ref[new] = ref;
|
||||
RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id = new;
|
||||
RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref = ref;
|
||||
np->rx.req_prod_pvt++;
|
||||
}
|
||||
|
||||
int xennet_get_extras(struct netfront_info *np,
|
||||
struct netif_extra_info *extras, RING_IDX rp)
|
||||
|
||||
{
|
||||
struct netif_extra_info *extra;
|
||||
RING_IDX cons = np->rx.rsp_cons;
|
||||
int err = 0;
|
||||
|
||||
do {
|
||||
struct sk_buff *skb;
|
||||
grant_ref_t ref;
|
||||
|
||||
if (unlikely(cons + 1 == rp)) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Missing extra info\n");
|
||||
err = -EBADR;
|
||||
break;
|
||||
}
|
||||
|
||||
extra = (struct netif_extra_info *)
|
||||
RING_GET_RESPONSE(&np->rx, ++cons);
|
||||
|
||||
if (unlikely(!extra->type ||
|
||||
extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Invalid extra type: %d\n",
|
||||
extra->type);
|
||||
err = -EINVAL;
|
||||
} else
|
||||
memcpy(&extras[extra->type - 1], extra, sizeof(*extra));
|
||||
|
||||
skb = xennet_get_rx_skb(np, cons);
|
||||
ref = xennet_get_rx_ref(np, cons);
|
||||
xennet_move_rx_slot(np, skb, ref);
|
||||
} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
|
||||
|
||||
np->rx.rsp_cons = cons;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int xennet_get_responses(struct netfront_info *np,
|
||||
struct netfront_rx_info *rinfo, RING_IDX rp,
|
||||
struct sk_buff_head *list, int count)
|
||||
{
|
||||
struct mmu_update *mmu = np->rx_mmu + count;
|
||||
struct multicall_entry *mcl = np->rx_mcl + count;
|
||||
struct netif_rx_response *rx = &rinfo->rx;
|
||||
struct netif_extra_info *extras = rinfo->extras;
|
||||
RING_IDX cons = np->rx.rsp_cons;
|
||||
struct sk_buff *skb = xennet_get_rx_skb(np, cons);
|
||||
grant_ref_t ref = xennet_get_rx_ref(np, cons);
|
||||
int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
|
||||
int frags = 1;
|
||||
int err = 0;
|
||||
|
||||
if (rx->flags & NETRXF_extra_info) {
|
||||
err = xennet_get_extras(np, extras, rp);
|
||||
cons = np->rx.rsp_cons;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
unsigned long mfn;
|
||||
|
||||
if (unlikely(rx->status < 0 ||
|
||||
rx->offset + rx->status > PAGE_SIZE)) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("rx->offset: %x, size: %u\n",
|
||||
rx->offset, rx->status);
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This definitely indicates a bug, either in this driver or in
|
||||
* the backend driver. In future this should flag the bad
|
||||
* situation to the system controller to reboot the backed.
|
||||
*/
|
||||
if (ref == GRANT_INVALID_REF) {
|
||||
WPRINTK("Bad rx response id %d.\n", rx->id);
|
||||
err = -EINVAL;
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* Memory pressure, insufficient buffer headroom, ... */
|
||||
if ((mfn = gnttab_end_foreign_transfer_ref(ref)) == 0) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n",
|
||||
rx->id, rx->status);
|
||||
xennet_move_rx_slot(np, skb, ref);
|
||||
err = -ENOMEM;
|
||||
goto next;
|
||||
}
|
||||
|
||||
gnttab_release_grant_reference(&np->gref_rx_head, ref);
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
/* Remap the page. */
|
||||
struct page *page = skb_shinfo(skb)->frags[0].page;
|
||||
unsigned long pfn = page_to_pfn(page);
|
||||
void *vaddr = page_address(page);
|
||||
|
||||
MULTI_update_va_mapping(mcl, (unsigned long)vaddr,
|
||||
pfn_pte_ma(mfn, PAGE_KERNEL),
|
||||
0);
|
||||
mcl++;
|
||||
mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
|
||||
| MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = pfn;
|
||||
mmu++;
|
||||
|
||||
set_phys_to_machine(pfn, mfn);
|
||||
}
|
||||
|
||||
__skb_queue_tail(list, skb);
|
||||
|
||||
next:
|
||||
if (!(rx->flags & NETRXF_more_data))
|
||||
break;
|
||||
|
||||
if (cons + frags == rp) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Need more frags\n");
|
||||
err = -ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
rx = RING_GET_RESPONSE(&np->rx, cons + frags);
|
||||
skb = xennet_get_rx_skb(np, cons + frags);
|
||||
ref = xennet_get_rx_ref(np, cons + frags);
|
||||
frags++;
|
||||
}
|
||||
|
||||
if (unlikely(frags > max)) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Too many frags\n");
|
||||
err = -E2BIG;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static RING_IDX xennet_fill_frags(struct netfront_info *np,
|
||||
struct sk_buff *skb,
|
||||
struct sk_buff_head *list)
|
||||
{
|
||||
struct skb_shared_info *shinfo = skb_shinfo(skb);
|
||||
int nr_frags = shinfo->nr_frags;
|
||||
RING_IDX cons = np->rx.rsp_cons;
|
||||
skb_frag_t *frag = shinfo->frags + nr_frags;
|
||||
struct sk_buff *nskb;
|
||||
|
||||
while ((nskb = __skb_dequeue(list))) {
|
||||
struct netif_rx_response *rx =
|
||||
RING_GET_RESPONSE(&np->rx, ++cons);
|
||||
|
||||
frag->page = skb_shinfo(nskb)->frags[0].page;
|
||||
frag->page_offset = rx->offset;
|
||||
frag->size = rx->status;
|
||||
|
||||
skb->data_len += rx->status;
|
||||
|
||||
skb_shinfo(nskb)->nr_frags = 0;
|
||||
kfree_skb(nskb);
|
||||
|
||||
frag++;
|
||||
nr_frags++;
|
||||
}
|
||||
|
||||
shinfo->nr_frags = nr_frags;
|
||||
return cons;
|
||||
}
|
||||
|
||||
static int xennet_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso)
|
||||
{
|
||||
if (!gso->u.gso.size) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("GSO size must not be zero.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Currently only TCPv4 S.O. is supported. */
|
||||
if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
skb_shinfo(skb)->gso_size = gso->u.gso.size;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
|
||||
/* Header must be checked, and gso_segs computed. */
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
|
||||
skb_shinfo(skb)->gso_segs = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
{
|
||||
struct netfront_info *np = netdev_priv(dev);
|
||||
struct sk_buff *skb, *nskb;
|
||||
struct netif_rx_response *rx;
|
||||
struct sk_buff *skb;
|
||||
struct netfront_rx_info rinfo;
|
||||
struct netif_rx_response *rx = &rinfo.rx;
|
||||
struct netif_extra_info *extras = rinfo.extras;
|
||||
RING_IDX i, rp;
|
||||
struct mmu_update *mmu = np->rx_mmu;
|
||||
struct multicall_entry *mcl = np->rx_mcl;
|
||||
struct multicall_entry *mcl;
|
||||
int work_done, budget, more_to_do = 1;
|
||||
struct sk_buff_head rxq;
|
||||
struct sk_buff_head errq;
|
||||
struct sk_buff_head tmpq;
|
||||
unsigned long flags;
|
||||
unsigned long mfn;
|
||||
grant_ref_t ref;
|
||||
unsigned int len;
|
||||
int pages_done;
|
||||
int err;
|
||||
|
||||
spin_lock(&np->rx_lock);
|
||||
|
||||
@@ -863,53 +1135,66 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
}
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
skb_queue_head_init(&errq);
|
||||
skb_queue_head_init(&tmpq);
|
||||
|
||||
if ((budget = *pbudget) > dev->quota)
|
||||
budget = dev->quota;
|
||||
rp = np->rx.sring->rsp_prod;
|
||||
rmb(); /* Ensure we see queued responses up to 'rp'. */
|
||||
|
||||
for (i = np->rx.rsp_cons, work_done = 0;
|
||||
for (i = np->rx.rsp_cons, work_done = 0, pages_done = 0;
|
||||
(i != rp) && (work_done < budget);
|
||||
i++, work_done++) {
|
||||
rx = RING_GET_RESPONSE(&np->rx, i);
|
||||
np->rx.rsp_cons = ++i, work_done++) {
|
||||
memcpy(rx, RING_GET_RESPONSE(&np->rx, i), sizeof(*rx));
|
||||
memset(extras, 0, sizeof(extras));
|
||||
|
||||
/*
|
||||
* This definitely indicates a bug, either in this driver or in
|
||||
* the backend driver. In future this should flag the bad
|
||||
* situation to the system controller to reboot the backed.
|
||||
*/
|
||||
if ((ref = np->grant_rx_ref[rx->id]) == GRANT_INVALID_REF) {
|
||||
WPRINTK("Bad rx response id %d.\n", rx->id);
|
||||
err = xennet_get_responses(np, &rinfo, rp, &tmpq, pages_done);
|
||||
pages_done += skb_queue_len(&tmpq);
|
||||
|
||||
if (unlikely(err)) {
|
||||
err:
|
||||
i = np->rx.rsp_cons + skb_queue_len(&tmpq) - 1;
|
||||
work_done--;
|
||||
while ((skb = __skb_dequeue(&tmpq)))
|
||||
__skb_queue_tail(&errq, skb);
|
||||
np->stats.rx_errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Memory pressure, insufficient buffer headroom, ... */
|
||||
if ((mfn = gnttab_end_foreign_transfer_ref(ref)) == 0) {
|
||||
if (net_ratelimit())
|
||||
WPRINTK("Unfulfilled rx req (id=%d, st=%d).\n",
|
||||
rx->id, rx->status);
|
||||
RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->id =
|
||||
rx->id;
|
||||
RING_GET_REQUEST(&np->rx, np->rx.req_prod_pvt)->gref =
|
||||
ref;
|
||||
np->rx.req_prod_pvt++;
|
||||
RING_PUSH_REQUESTS(&np->rx);
|
||||
work_done--;
|
||||
continue;
|
||||
skb = __skb_dequeue(&tmpq);
|
||||
|
||||
if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
|
||||
struct netif_extra_info *gso;
|
||||
gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
|
||||
|
||||
if (unlikely(xennet_set_skb_gso(skb, gso))) {
|
||||
__skb_queue_head(&tmpq, skb);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
gnttab_release_grant_reference(&np->gref_rx_head, ref);
|
||||
np->grant_rx_ref[rx->id] = GRANT_INVALID_REF;
|
||||
skb->nh.raw = (void *)skb_shinfo(skb)->frags[0].page;
|
||||
skb->h.raw = skb->nh.raw + rx->offset;
|
||||
|
||||
skb = np->rx_skbs[rx->id];
|
||||
add_id_to_freelist(np->rx_skbs, rx->id);
|
||||
len = rx->status;
|
||||
if (len > RX_COPY_THRESHOLD)
|
||||
len = RX_COPY_THRESHOLD;
|
||||
skb_put(skb, len);
|
||||
|
||||
/* NB. We handle skb overflow later. */
|
||||
skb->data = skb->head + rx->offset;
|
||||
skb->len = rx->status;
|
||||
skb->tail = skb->data + skb->len;
|
||||
if (rx->status > len) {
|
||||
skb_shinfo(skb)->frags[0].page_offset =
|
||||
rx->offset + len;
|
||||
skb_shinfo(skb)->frags[0].size = rx->status - len;
|
||||
skb->data_len = rx->status - len;
|
||||
} else {
|
||||
skb_shinfo(skb)->frags[0].page = NULL;
|
||||
skb_shinfo(skb)->nr_frags = 0;
|
||||
}
|
||||
|
||||
i = xennet_fill_frags(np, skb, &tmpq);
|
||||
skb->truesize += skb->data_len;
|
||||
skb->len += skb->data_len;
|
||||
|
||||
/*
|
||||
* Old backends do not assert data_validated but we
|
||||
@@ -925,96 +1210,38 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
skb->proto_csum_blank = !!(rx->flags & NETRXF_csum_blank);
|
||||
|
||||
np->stats.rx_packets++;
|
||||
np->stats.rx_bytes += rx->status;
|
||||
|
||||
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
|
||||
/* Remap the page. */
|
||||
MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
|
||||
pfn_pte_ma(mfn, PAGE_KERNEL),
|
||||
0);
|
||||
mcl++;
|
||||
mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
|
||||
| MMU_MACHPHYS_UPDATE;
|
||||
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
|
||||
mmu++;
|
||||
|
||||
set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT,
|
||||
mfn);
|
||||
}
|
||||
np->stats.rx_bytes += skb->len;
|
||||
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
}
|
||||
|
||||
/* Some pages are no longer absent... */
|
||||
balloon_update_driver_allowance(-work_done);
|
||||
balloon_update_driver_allowance(-pages_done);
|
||||
|
||||
/* Do all the remapping work, and M2P updates, in one big hypercall. */
|
||||
if (likely((mcl - np->rx_mcl) != 0)) {
|
||||
if (likely(pages_done)) {
|
||||
mcl = np->rx_mcl + pages_done;
|
||||
mcl->op = __HYPERVISOR_mmu_update;
|
||||
mcl->args[0] = (unsigned long)np->rx_mmu;
|
||||
mcl->args[1] = mmu - np->rx_mmu;
|
||||
mcl->args[1] = pages_done;
|
||||
mcl->args[2] = 0;
|
||||
mcl->args[3] = DOMID_SELF;
|
||||
mcl++;
|
||||
(void)HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
|
||||
(void)HYPERVISOR_multicall(np->rx_mcl, pages_done + 1);
|
||||
}
|
||||
|
||||
while ((skb = __skb_dequeue(&errq)))
|
||||
kfree_skb(skb);
|
||||
|
||||
while ((skb = __skb_dequeue(&rxq)) != NULL) {
|
||||
if (skb->len > (dev->mtu + ETH_HLEN + 4)) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_INFO "Received packet too big for "
|
||||
"MTU (%d > %d)\n",
|
||||
skb->len - ETH_HLEN - 4, dev->mtu);
|
||||
skb->len = 0;
|
||||
skb->tail = skb->data;
|
||||
init_skb_shinfo(skb);
|
||||
dev_kfree_skb(skb);
|
||||
continue;
|
||||
}
|
||||
struct page *page = (struct page *)skb->nh.raw;
|
||||
void *vaddr = page_address(page);
|
||||
|
||||
/*
|
||||
* Enough room in skbuff for the data we were passed? Also,
|
||||
* Linux expects at least 16 bytes headroom in each rx buffer.
|
||||
*/
|
||||
if (unlikely(skb->tail > skb->end) ||
|
||||
unlikely((skb->data - skb->head) < 16)) {
|
||||
if (net_ratelimit()) {
|
||||
if (skb->tail > skb->end)
|
||||
printk(KERN_INFO "Received packet "
|
||||
"is %zd bytes beyond tail.\n",
|
||||
skb->tail - skb->end);
|
||||
else
|
||||
printk(KERN_INFO "Received packet "
|
||||
"is %zd bytes before head.\n",
|
||||
16 - (skb->data - skb->head));
|
||||
}
|
||||
memcpy(skb->data, vaddr + (skb->h.raw - skb->nh.raw),
|
||||
skb_headlen(skb));
|
||||
|
||||
nskb = __dev_alloc_skb(skb->len + 2,
|
||||
GFP_ATOMIC|__GFP_NOWARN);
|
||||
if (nskb != NULL) {
|
||||
skb_reserve(nskb, 2);
|
||||
skb_put(nskb, skb->len);
|
||||
memcpy(nskb->data, skb->data, skb->len);
|
||||
/* Copy any other fields we already set up. */
|
||||
nskb->dev = skb->dev;
|
||||
nskb->ip_summed = skb->ip_summed;
|
||||
nskb->proto_data_valid = skb->proto_data_valid;
|
||||
nskb->proto_csum_blank = skb->proto_csum_blank;
|
||||
}
|
||||
if (page != skb_shinfo(skb)->frags[0].page)
|
||||
__free_page(page);
|
||||
|
||||
/* Reinitialise and then destroy the old skbuff. */
|
||||
skb->len = 0;
|
||||
skb->tail = skb->data;
|
||||
init_skb_shinfo(skb);
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
/* Switch old for new, if we copied the buffer. */
|
||||
if ((skb = nskb) == NULL)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the shinfo area, which is hidden behind the data. */
|
||||
init_skb_shinfo(skb);
|
||||
/* Ethernet work: Delayed to here as it peeks the header. */
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
|
||||
@@ -1023,8 +1250,6 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
dev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
np->rx.rsp_cons = i;
|
||||
|
||||
/* If we get a callback with very few responses, reduce fill target. */
|
||||
/* NB. Note exponential increase, linear decrease. */
|
||||
if (((np->rx.req_prod_pvt - np->rx.sring->rsp_prod) >
|
||||
@@ -1103,9 +1328,7 @@ static int xennet_set_tso(struct net_device *dev, u32 data)
|
||||
if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
|
||||
"feature-gso-tcpv4", "%d", &val) < 0)
|
||||
val = 0;
|
||||
#if 0 /* KAF: After the protocol is finalised. */
|
||||
if (!val)
|
||||
#endif
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
@@ -1128,6 +1351,7 @@ static void network_connect(struct net_device *dev)
|
||||
struct netfront_info *np = netdev_priv(dev);
|
||||
int i, requeue_idx;
|
||||
struct sk_buff *skb;
|
||||
grant_ref_t ref;
|
||||
|
||||
xennet_set_features(dev);
|
||||
|
||||
@@ -1158,20 +1382,24 @@ static void network_connect(struct net_device *dev)
|
||||
}
|
||||
|
||||
/* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
|
||||
for (requeue_idx = 0, i = 1; i <= NET_RX_RING_SIZE; i++) {
|
||||
if ((unsigned long)np->rx_skbs[i] < PAGE_OFFSET)
|
||||
for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++) {
|
||||
if (!np->rx_skbs[i])
|
||||
continue;
|
||||
|
||||
skb = np->rx_skbs[requeue_idx] = xennet_get_rx_skb(np, i);
|
||||
ref = np->grant_rx_ref[requeue_idx] = xennet_get_rx_ref(np, i);
|
||||
|
||||
gnttab_grant_foreign_transfer_ref(
|
||||
np->grant_rx_ref[i], np->xbdev->otherend_id,
|
||||
__pa(np->rx_skbs[i]->data) >> PAGE_SHIFT);
|
||||
RING_GET_REQUEST(&np->rx, requeue_idx)->gref =
|
||||
np->grant_rx_ref[i];
|
||||
RING_GET_REQUEST(&np->rx, requeue_idx)->id = i;
|
||||
ref, np->xbdev->otherend_id,
|
||||
page_to_pfn(skb_shinfo(skb)->frags->page));
|
||||
|
||||
RING_GET_REQUEST(&np->rx, requeue_idx)->gref = ref;
|
||||
RING_GET_REQUEST(&np->rx, requeue_idx)->id = requeue_idx;
|
||||
|
||||
requeue_idx++;
|
||||
}
|
||||
|
||||
np->rx.req_prod_pvt = requeue_idx;
|
||||
RING_PUSH_REQUESTS(&np->rx);
|
||||
|
||||
/*
|
||||
* Step 3: All public and private state should now be sane. Get
|
||||
@@ -1392,8 +1620,8 @@ static struct net_device * __devinit create_netdev(int handle,
|
||||
np->grant_tx_ref[i] = GRANT_INVALID_REF;
|
||||
}
|
||||
|
||||
for (i = 0; i <= NET_RX_RING_SIZE; i++) {
|
||||
np->rx_skbs[i] = (void *)((unsigned long) i+1);
|
||||
for (i = 0; i < NET_RX_RING_SIZE; i++) {
|
||||
np->rx_skbs[i] = NULL;
|
||||
np->grant_rx_ref[i] = GRANT_INVALID_REF;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,10 @@ static int __devinit pcistub_match_one(struct pci_dev *dev,
|
||||
&& dev->bus->number == pdev_id->bus
|
||||
&& dev->devfn == pdev_id->devfn)
|
||||
return 1;
|
||||
|
||||
/* Sometimes topmost bridge links to itself. */
|
||||
if (dev == dev->bus->self)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -445,6 +445,9 @@ static struct xenbus_driver xenbus_pciback_driver = {
|
||||
|
||||
int __init pciback_xenbus_register(void)
|
||||
{
|
||||
if (!is_running_on_xen())
|
||||
return -ENODEV;
|
||||
|
||||
return xenbus_register_backend(&xenbus_pciback_driver);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn,
|
||||
.size = size,
|
||||
};
|
||||
struct pcifront_sd *sd = bus->sysdata;
|
||||
struct pcifront_device *pdev = sd->pdev;
|
||||
struct pcifront_device *pdev = pcifront_get_pdev(sd);
|
||||
|
||||
if (verbose_request)
|
||||
dev_info(&pdev->xdev->dev,
|
||||
@@ -144,7 +144,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn,
|
||||
.value = val,
|
||||
};
|
||||
struct pcifront_sd *sd = bus->sysdata;
|
||||
struct pcifront_device *pdev = sd->pdev;
|
||||
struct pcifront_device *pdev = pcifront_get_pdev(sd);
|
||||
|
||||
if (verbose_request)
|
||||
dev_info(&pdev->xdev->dev,
|
||||
@@ -207,12 +207,13 @@ int pcifront_scan_root(struct pcifront_device *pdev,
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
sd->domain = domain;
|
||||
sd->pdev = pdev;
|
||||
pcifront_init_sd(sd, domain, pdev);
|
||||
|
||||
b = pci_scan_bus_parented(&pdev->xdev->dev, bus, &pcifront_bus_ops, sd);
|
||||
b = pci_scan_bus_parented(&pdev->xdev->dev, bus,
|
||||
&pcifront_bus_ops, sd);
|
||||
if (!b) {
|
||||
dev_err(&pdev->xdev->dev, "Error creating PCI Frontend Bus!\n");
|
||||
dev_err(&pdev->xdev->dev,
|
||||
"Error creating PCI Frontend Bus!\n");
|
||||
err = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/mm.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/gnttab.h>
|
||||
#include "pcifront.h"
|
||||
|
||||
#define INVALID_GRANT_REF (0)
|
||||
@@ -283,11 +284,10 @@ static struct xenbus_driver xenbus_pcifront_driver = {
|
||||
|
||||
static int __init pcifront_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
if (!is_running_on_xen())
|
||||
return -ENODEV;
|
||||
|
||||
err = xenbus_register_frontend(&xenbus_pcifront_driver);
|
||||
|
||||
return err;
|
||||
return xenbus_register_frontend(&xenbus_pcifront_driver);
|
||||
}
|
||||
|
||||
/* Initialize after the Xen PCI Frontend Stub is initialized */
|
||||
|
||||
@@ -270,6 +270,7 @@ static int __init privcmd_init(void)
|
||||
set_bit(__HYPERVISOR_sched_op_compat, hypercall_permission_map);
|
||||
set_bit(__HYPERVISOR_event_channel_op_compat,
|
||||
hypercall_permission_map);
|
||||
set_bit(__HYPERVISOR_hvm_op, hypercall_permission_map);
|
||||
|
||||
privcmd_intf = create_xen_proc_entry("privcmd", 0400);
|
||||
if (privcmd_intf != NULL)
|
||||
|
||||
@@ -55,7 +55,6 @@ struct packet {
|
||||
|
||||
enum {
|
||||
PACKET_FLAG_DISCARD_RESPONSE = 1,
|
||||
PACKET_FLAG_CHECK_RESPONSESTATUS = 2,
|
||||
};
|
||||
|
||||
/* local variables */
|
||||
@@ -201,21 +200,6 @@ static void packet_free(struct packet *pak)
|
||||
kfree(pak);
|
||||
}
|
||||
|
||||
static int packet_set(struct packet *pak,
|
||||
const unsigned char *buffer, u32 size)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned char *buf = kmalloc(size, GFP_KERNEL);
|
||||
|
||||
if (buf) {
|
||||
pak->data_buffer = buf;
|
||||
memcpy(buf, buffer, size);
|
||||
pak->data_len = size;
|
||||
} else {
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write data to the shared memory and send it to the FE.
|
||||
@@ -225,29 +209,6 @@ static int packet_write(struct packet *pak,
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if ((pak->flags & PACKET_FLAG_CHECK_RESPONSESTATUS)) {
|
||||
#ifdef CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS
|
||||
u32 res;
|
||||
|
||||
if (copy_from_buffer(&res,
|
||||
&data[2 + 4], sizeof (res),
|
||||
isuserbuffer)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (res != 0) {
|
||||
/*
|
||||
* Close down this device. Should have the
|
||||
* FE notified about closure.
|
||||
*/
|
||||
if (!pak->tpmif) {
|
||||
return -EFAULT;
|
||||
}
|
||||
pak->tpmif->status = DISCONNECTING;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (0 != (pak->flags & PACKET_FLAG_DISCARD_RESPONSE)) {
|
||||
/* Don't send a respone to this packet. Just acknowledge it. */
|
||||
rc = size;
|
||||
|
||||
@@ -58,6 +58,9 @@ struct xenbus_dev_data {
|
||||
/* In-progress transaction. */
|
||||
struct list_head transactions;
|
||||
|
||||
/* Active watches. */
|
||||
struct list_head watches;
|
||||
|
||||
/* Partial request. */
|
||||
unsigned int len;
|
||||
union {
|
||||
@@ -70,6 +73,8 @@ struct xenbus_dev_data {
|
||||
char read_buffer[PAGE_SIZE];
|
||||
unsigned int read_cons, read_prod;
|
||||
wait_queue_head_t read_waitq;
|
||||
|
||||
struct mutex reply_mutex;
|
||||
};
|
||||
|
||||
static struct proc_dir_entry *xenbus_dev_intf;
|
||||
@@ -100,14 +105,60 @@ static void queue_reply(struct xenbus_dev_data *u,
|
||||
{
|
||||
int i;
|
||||
|
||||
mutex_lock(&u->reply_mutex);
|
||||
|
||||
for (i = 0; i < len; i++, u->read_prod++)
|
||||
u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
|
||||
|
||||
BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
|
||||
|
||||
mutex_unlock(&u->reply_mutex);
|
||||
|
||||
wake_up(&u->read_waitq);
|
||||
}
|
||||
|
||||
struct watch_adapter
|
||||
{
|
||||
struct list_head list;
|
||||
struct xenbus_watch watch;
|
||||
struct xenbus_dev_data *dev_data;
|
||||
char *token;
|
||||
};
|
||||
|
||||
static void free_watch_adapter (struct watch_adapter *watch)
|
||||
{
|
||||
kfree(watch->watch.node);
|
||||
kfree(watch->token);
|
||||
kfree(watch);
|
||||
}
|
||||
|
||||
static void watch_fired(struct xenbus_watch *watch,
|
||||
const char **vec,
|
||||
unsigned int len)
|
||||
{
|
||||
struct watch_adapter *adap =
|
||||
container_of(watch, struct watch_adapter, watch);
|
||||
struct xsd_sockmsg hdr;
|
||||
const char *path, *token;
|
||||
int path_len, tok_len, body_len;
|
||||
|
||||
path = vec[XS_WATCH_PATH];
|
||||
token = adap->token;
|
||||
|
||||
path_len = strlen(path) + 1;
|
||||
tok_len = strlen(token) + 1;
|
||||
body_len = path_len + tok_len;
|
||||
|
||||
hdr.type = XS_WATCH_EVENT;
|
||||
hdr.len = body_len;
|
||||
|
||||
queue_reply(adap->dev_data, (char *)&hdr, sizeof(hdr));
|
||||
queue_reply(adap->dev_data, (char *)path, path_len);
|
||||
queue_reply(adap->dev_data, (char *)token, tok_len);
|
||||
}
|
||||
|
||||
static LIST_HEAD(watch_list);
|
||||
|
||||
static ssize_t xenbus_dev_write(struct file *filp,
|
||||
const char __user *ubuf,
|
||||
size_t len, loff_t *ppos)
|
||||
@@ -116,6 +167,9 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
struct xenbus_dev_transaction *trans = NULL;
|
||||
uint32_t msg_type;
|
||||
void *reply;
|
||||
char *path, *token;
|
||||
struct watch_adapter *watch, *tmp_watch;
|
||||
int err;
|
||||
|
||||
if ((len + u->len) > sizeof(u->u.buffer))
|
||||
return -EINVAL;
|
||||
@@ -169,6 +223,56 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
kfree(reply);
|
||||
break;
|
||||
|
||||
case XS_WATCH:
|
||||
case XS_UNWATCH:
|
||||
path = u->u.buffer + sizeof(u->u.msg);
|
||||
token = memchr(path, 0, u->u.msg.len);
|
||||
if (token == NULL)
|
||||
return -EILSEQ;
|
||||
token++;
|
||||
|
||||
if (msg_type == XS_WATCH) {
|
||||
static const char * XS_WATCH_RESP = "OK";
|
||||
struct xsd_sockmsg hdr;
|
||||
|
||||
watch = kmalloc(sizeof(*watch), GFP_KERNEL);
|
||||
watch->watch.node = kmalloc(strlen(path)+1,
|
||||
GFP_KERNEL);
|
||||
strcpy((char *)watch->watch.node, path);
|
||||
watch->watch.callback = watch_fired;
|
||||
watch->token = kmalloc(strlen(token)+1, GFP_KERNEL);
|
||||
strcpy(watch->token, token);
|
||||
watch->dev_data = u;
|
||||
|
||||
err = register_xenbus_watch(&watch->watch);
|
||||
if (err) {
|
||||
free_watch_adapter(watch);
|
||||
return err;
|
||||
}
|
||||
|
||||
list_add(&watch->list, &u->watches);
|
||||
|
||||
hdr.type = XS_WATCH;
|
||||
hdr.len = strlen(XS_WATCH_RESP) + 1;
|
||||
queue_reply(u, (char *)&hdr, sizeof(hdr));
|
||||
queue_reply(u, (char *)XS_WATCH_RESP, hdr.len);
|
||||
} else {
|
||||
list_for_each_entry_safe(watch, tmp_watch,
|
||||
&u->watches, list) {
|
||||
if (!strcmp(watch->token, token) &&
|
||||
!strcmp(watch->watch.node, path))
|
||||
break;
|
||||
{
|
||||
unregister_xenbus_watch(&watch->watch);
|
||||
list_del(&watch->list);
|
||||
free_watch_adapter(watch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -191,8 +295,11 @@ static int xenbus_dev_open(struct inode *inode, struct file *filp)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&u->transactions);
|
||||
INIT_LIST_HEAD(&u->watches);
|
||||
init_waitqueue_head(&u->read_waitq);
|
||||
|
||||
mutex_init(&u->reply_mutex);
|
||||
|
||||
filp->private_data = u;
|
||||
|
||||
return 0;
|
||||
@@ -202,6 +309,7 @@ static int xenbus_dev_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct xenbus_dev_data *u = filp->private_data;
|
||||
struct xenbus_dev_transaction *trans, *tmp;
|
||||
struct watch_adapter *watch, *tmp_watch;
|
||||
|
||||
list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
|
||||
xenbus_transaction_end(trans->handle, 1);
|
||||
@@ -209,6 +317,12 @@ static int xenbus_dev_release(struct inode *inode, struct file *filp)
|
||||
kfree(trans);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(watch, tmp_watch, &u->watches, list) {
|
||||
unregister_xenbus_watch(&watch->watch);
|
||||
list_del(&watch->list);
|
||||
free_watch_adapter(watch);
|
||||
}
|
||||
|
||||
kfree(u);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -141,7 +141,9 @@ static int read_otherend_details(struct xenbus_device *xendev,
|
||||
}
|
||||
if (strlen(xendev->otherend) == 0 ||
|
||||
!xenbus_exists(XBT_NIL, xendev->otherend, "")) {
|
||||
xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
|
||||
xenbus_dev_fatal(xendev, -ENOENT,
|
||||
"unable to read other end from %s. "
|
||||
"missing or inaccessible.",
|
||||
xendev->nodename);
|
||||
free_otherend_details(xendev);
|
||||
return -ENOENT;
|
||||
|
||||
@@ -187,16 +187,14 @@ MULTI_update_va_mapping(
|
||||
mcl->args[0] = va;
|
||||
#if defined(CONFIG_X86_64)
|
||||
mcl->args[1] = new_val.pte;
|
||||
mcl->args[2] = flags;
|
||||
#elif defined(CONFIG_X86_PAE)
|
||||
mcl->args[1] = new_val.pte_low;
|
||||
mcl->args[2] = new_val.pte_high;
|
||||
mcl->args[3] = flags;
|
||||
#else
|
||||
mcl->args[1] = new_val.pte_low;
|
||||
mcl->args[2] = 0;
|
||||
mcl->args[3] = flags;
|
||||
#endif
|
||||
mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -208,19 +206,15 @@ MULTI_update_va_mapping_otherdomain(
|
||||
mcl->args[0] = va;
|
||||
#if defined(CONFIG_X86_64)
|
||||
mcl->args[1] = new_val.pte;
|
||||
mcl->args[2] = flags;
|
||||
mcl->args[3] = domid;
|
||||
#elif defined(CONFIG_X86_PAE)
|
||||
mcl->args[1] = new_val.pte_low;
|
||||
mcl->args[2] = new_val.pte_high;
|
||||
mcl->args[3] = flags;
|
||||
mcl->args[4] = domid;
|
||||
#else
|
||||
mcl->args[1] = new_val.pte_low;
|
||||
mcl->args[2] = 0;
|
||||
mcl->args[3] = flags;
|
||||
mcl->args[4] = domid;
|
||||
#endif
|
||||
mcl->args[MULTI_UVMFLAGS_INDEX] = flags;
|
||||
mcl->args[MULTI_UVMDOMID_INDEX] = domid;
|
||||
}
|
||||
|
||||
#endif /* __HYPERVISOR_H__ */
|
||||
@@ -12,6 +12,9 @@ typedef struct {
|
||||
int size;
|
||||
struct semaphore sem;
|
||||
void *ldt;
|
||||
#ifdef CONFIG_XEN
|
||||
int has_foreign_mappings;
|
||||
#endif
|
||||
} mm_context_t;
|
||||
|
||||
/* mm/memory.c:exit_mmap hook */
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
(*(volatile signed char *)(&(x)->slock) <= 0)
|
||||
|
||||
#define __raw_spin_lock_string \
|
||||
"\n1:\n" \
|
||||
"\n1:\t" \
|
||||
LOCK \
|
||||
"decb %0\n\t" \
|
||||
"jns 3f\n" \
|
||||
@@ -35,7 +35,7 @@
|
||||
"3:\n\t"
|
||||
|
||||
#define __raw_spin_lock_string_flags \
|
||||
"\n1:\n" \
|
||||
"\n1:\t" \
|
||||
LOCK \
|
||||
"decb %0\n\t" \
|
||||
"jns 4f\n\t" \
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef struct {
|
||||
struct semaphore sem;
|
||||
#ifdef CONFIG_XEN
|
||||
unsigned pinned:1;
|
||||
unsigned has_foreign_mappings:1;
|
||||
struct list_head unpinned;
|
||||
#endif
|
||||
} mm_context_t;
|
||||
|
||||
@@ -11,16 +11,30 @@
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ia64__
|
||||
|
||||
struct pcifront_device;
|
||||
struct pci_bus;
|
||||
|
||||
struct pcifront_sd {
|
||||
int domain;
|
||||
struct pcifront_device *pdev;
|
||||
};
|
||||
|
||||
struct pci_bus;
|
||||
static inline struct pcifront_device *
|
||||
pcifront_get_pdev(struct pcifront_sd *sd)
|
||||
{
|
||||
return sd->pdev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_DOMAINS
|
||||
static inline void pcifront_init_sd(struct pcifront_sd *sd, int domain,
|
||||
struct pcifront_device *pdev)
|
||||
{
|
||||
sd->domain = domain;
|
||||
sd->pdev = pdev;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PCI_DOMAINS)
|
||||
static inline int pci_domain_nr(struct pci_bus *bus)
|
||||
{
|
||||
struct pcifront_sd *sd = bus->sysdata;
|
||||
@@ -32,6 +46,30 @@ static inline int pci_proc_domain(struct pci_bus *bus)
|
||||
}
|
||||
#endif /* CONFIG_PCI_DOMAINS */
|
||||
|
||||
#else /* __ia64__ */
|
||||
|
||||
#include <asm/pci.h>
|
||||
#define pcifront_sd pci_controller
|
||||
|
||||
static inline struct pcifront_device *
|
||||
pcifront_get_pdev(struct pcifront_sd *sd)
|
||||
{
|
||||
return (struct pcifront_device *)sd->platform_data;
|
||||
}
|
||||
|
||||
static inline void pcifront_init_sd(struct pcifront_sd *sd, int domain,
|
||||
struct pcifront_device *pdev)
|
||||
{
|
||||
sd->segment = domain;
|
||||
sd->acpi_handle = NULL;
|
||||
sd->iommu = NULL;
|
||||
sd->windows = 0;
|
||||
sd->window = NULL;
|
||||
sd->platform_data = pdev;
|
||||
}
|
||||
|
||||
#endif /* __ia64__ */
|
||||
|
||||
extern spinlock_t pci_bus_lock;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
@@ -33,9 +33,7 @@ LIBS += -lcrypto
|
||||
LIBS += -lz
|
||||
LIBS += -L$(XEN_XENSTORE) -lxenstore
|
||||
|
||||
AIOLIBS := -L $(LIBAIO_DIR)
|
||||
AIOLIBS += -laio
|
||||
AIOLIBS += -static
|
||||
AIOLIBS := $(LIBAIO_DIR)/libaio.a
|
||||
|
||||
BLK-OBJS := block-aio.o
|
||||
BLK-OBJS += block-sync.o
|
||||
@@ -49,21 +47,18 @@ all: $(IBIN) qcow-util
|
||||
LINUX_ROOT := $(wildcard $(XEN_ROOT)/linux-2.6.*-xen-sparse)
|
||||
|
||||
|
||||
blktapctrl:
|
||||
blktapctrl: blktapctrl.c
|
||||
$(CC) $(CFLAGS) -o blktapctrl $(LIBS) blktapctrl.c
|
||||
|
||||
tapdisk: $(BLK-OBJS)
|
||||
tapdisk: $(BLK-OBJS) tapdisk.c
|
||||
$(CC) $(CFLAGS) -o tapdisk $(BLK-OBJS) tapdisk.c \
|
||||
$(AIOLIBS) $(LIBS)
|
||||
|
||||
.PHONY: qcow-util
|
||||
qcow-util: img2qcow qcow2raw qcow-create
|
||||
|
||||
qcow-util: $(BLK-OBJS)
|
||||
$(CC) $(CFLAGS) -o img2qcow $(BLK-OBJS) img2qcow.c \
|
||||
$(AIOLIBS) $(LIBS)
|
||||
$(CC) $(CFLAGS) -o qcow2raw $(BLK-OBJS) qcow2raw.c \
|
||||
$(AIOLIBS) $(LIBS)
|
||||
$(CC) $(CFLAGS) -o qcow-create $(BLK-OBJS) qcow-create.c \
|
||||
$(AIOLIBS) $(LIBS)
|
||||
img2qcow qcow2raw qcow-create: %: $(BLK-OBJS)
|
||||
$(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS)
|
||||
|
||||
install: all
|
||||
$(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(DESTDIR)$(INSTALL_DIR)
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#define MSG_SIZE 4096
|
||||
#define MAX_TIMEOUT 10
|
||||
#define MAX_RAND_VAL 0xFFFF
|
||||
#define MAX_ATTEMPTS 10
|
||||
|
||||
int run = 1;
|
||||
int max_timeout = MAX_TIMEOUT;
|
||||
@@ -626,13 +627,14 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
char *devname;
|
||||
tapdev_info_t *ctlinfo;
|
||||
int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count;
|
||||
int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
|
||||
struct xs_handle *h;
|
||||
struct pollfd pfd[NUM_POLL_FDS];
|
||||
pid_t process;
|
||||
|
||||
__init_blkif();
|
||||
openlog("BLKTAPCTRL", LOG_CONS|LOG_ODELAY, LOG_DAEMON);
|
||||
daemon(0,0);
|
||||
|
||||
print_drivers();
|
||||
init_driver_list();
|
||||
@@ -651,18 +653,28 @@ int main(int argc, char *argv[])
|
||||
goto open_failed;
|
||||
}
|
||||
|
||||
retry:
|
||||
/* Set up store connection and watch. */
|
||||
h = xs_daemon_open();
|
||||
if (h == NULL) {
|
||||
DPRINTF("xs_daemon_open failed -- "
|
||||
"is xenstore running?\n");
|
||||
goto open_failed;
|
||||
if (count < MAX_ATTEMPTS) {
|
||||
count++;
|
||||
sleep(2);
|
||||
goto retry;
|
||||
} else goto open_failed;
|
||||
}
|
||||
|
||||
ret = add_blockdevice_probe_watch(h, "Domain-0");
|
||||
if (ret != 0) {
|
||||
DPRINTF("adding device probewatch\n");
|
||||
goto open_failed;
|
||||
DPRINTF("Failed adding device probewatch\n");
|
||||
if (count < MAX_ATTEMPTS) {
|
||||
count++;
|
||||
sleep(2);
|
||||
xs_daemon_close(h);
|
||||
goto retry;
|
||||
} else goto open_failed;
|
||||
}
|
||||
|
||||
ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
|
||||
@@ -691,6 +703,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
xs_daemon_close(h);
|
||||
ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
|
||||
close(ctlfd);
|
||||
closelog();
|
||||
|
||||
@@ -35,10 +35,14 @@ IBINS :=
|
||||
|
||||
LIB = libblktap.a libblktap.so.$(MAJOR).$(MINOR)
|
||||
|
||||
.PHONY: all
|
||||
all: build
|
||||
|
||||
build:
|
||||
$(MAKE) libblktap
|
||||
.PHONY: build
|
||||
build: libblktap.a
|
||||
|
||||
.PHONY: libblktap
|
||||
libblktap: libblktap.a
|
||||
|
||||
install: all
|
||||
$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
|
||||
@@ -51,13 +55,13 @@ install: all
|
||||
clean:
|
||||
rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS
|
||||
|
||||
libblktap: $(OBJS)
|
||||
libblktap.a: $(OBJS)
|
||||
$(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared \
|
||||
-L$(XEN_XENSTORE) -l xenstore \
|
||||
-o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
|
||||
ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR)
|
||||
ln -sf libblktap.so.$(MAJOR) $@.so
|
||||
ar rc libblktap.a $@.so
|
||||
ln -sf libblktap.so.$(MAJOR) libblktap.so
|
||||
ar rc $@ libblktap.so
|
||||
|
||||
.PHONY: TAGS all build clean install libblktap
|
||||
|
||||
|
||||
+16
-2
@@ -239,8 +239,11 @@ case "$command" in
|
||||
exit 0
|
||||
fi
|
||||
|
||||
p=$(xenstore_read "$XENBUS_PATH/params")
|
||||
mode=$(xenstore_read "$XENBUS_PATH/mode")
|
||||
if [ -n "$t" ]
|
||||
then
|
||||
p=$(xenstore_read "$XENBUS_PATH/params")
|
||||
mode=$(xenstore_read "$XENBUS_PATH/mode")
|
||||
fi
|
||||
|
||||
case $t in
|
||||
phy)
|
||||
@@ -370,6 +373,13 @@ mount it read-write in a guest domain."
|
||||
release_lock "block"
|
||||
exit 0
|
||||
;;
|
||||
|
||||
"")
|
||||
claim_lock "block"
|
||||
success
|
||||
echo happy gun \"$t\" >>/tmp/block.$$
|
||||
release_lock "block"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
@@ -384,6 +394,10 @@ mount it read-write in a guest domain."
|
||||
losetup -d "$node"
|
||||
exit 0
|
||||
;;
|
||||
|
||||
"")
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ vif = [ 'type=ioemu, bridge=xenbr0' ]
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
#disk = [ 'phy:hda1,hda1,r' ]
|
||||
disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
|
||||
disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Configure the behaviour when a domain exits. There are three 'reasons'
|
||||
@@ -110,10 +110,6 @@ disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
|
||||
# New stuff
|
||||
device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Disk image for
|
||||
#cdrom=
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# boot on floppy (a), hard disk (c) or CD-ROM (d)
|
||||
#boot=[a|c|d]
|
||||
@@ -153,8 +149,8 @@ serial='pty'
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# enable audio support
|
||||
#audio=1
|
||||
# enable sound card support, [sb16|es1370|all|..,..], default none
|
||||
#soundhw='sb16'
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
@@ -30,7 +30,7 @@ all:
|
||||
.PHONY: install
|
||||
install: all
|
||||
[ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR)
|
||||
[ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR)
|
||||
install -m0644 $(TARGET) $(INSTALL_DIR)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
||||
+115
-102
@@ -16,7 +16,7 @@
|
||||
//* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
//**
|
||||
//** DSDT for Xen with Qemu device model
|
||||
//** DSDT for Xen with Qemu device model
|
||||
//**
|
||||
//**
|
||||
|
||||
@@ -50,21 +50,36 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
})
|
||||
|
||||
|
||||
Name(PICD, 0)
|
||||
Name(PICD, 0)
|
||||
|
||||
Method(_PIC, 1) {
|
||||
Method(_PIC, 1) {
|
||||
|
||||
Store(Arg0, PICD)
|
||||
}
|
||||
Store(Arg0, PICD)
|
||||
}
|
||||
Scope (\_SB)
|
||||
{
|
||||
Device (PCI0)
|
||||
/* Fix HCT test for 0x400 pci memory - need to report low 640 MB mem as motherboard resource */
|
||||
|
||||
Device(MEM0) {
|
||||
Name(_HID, EISAID("PNP0C02"))
|
||||
Name(_CRS, ResourceTemplate() {
|
||||
QWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
0x0009ffff,
|
||||
0x00000000,
|
||||
0x000a0000)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Device (PCI0)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0A03"))
|
||||
Name (_UID, 0x00)
|
||||
Name (_ADR, 0x00)
|
||||
Name (_BBN, 0x00)
|
||||
OperationRegion (PIRP, PCI_Config, 0x3c, 0x10)
|
||||
Name (_HID, EisaId ("PNP0A03"))
|
||||
Name (_UID, 0x00)
|
||||
Name (_ADR, 0x00)
|
||||
Name (_BBN, 0x00)
|
||||
OperationRegion (PIRP, PCI_Config, 0x3c, 0x10)
|
||||
Field(PIRP, ByteAcc, NoLock, Preserve){
|
||||
IRQ3,3,
|
||||
IRQ5,5,
|
||||
@@ -79,7 +94,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
|
||||
Name (PRT0, ResourceTemplate ()
|
||||
{
|
||||
/* bus number is from 0 - 255*/
|
||||
/* bus number is from 0 - 255*/
|
||||
WordBusNumber (ResourceConsumer, MinFixed, MaxFixed, SubDecode,
|
||||
0x0000,
|
||||
0x0000,
|
||||
@@ -122,7 +137,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
0x00000000,
|
||||
0x00030000)
|
||||
|
||||
/* reserve what device model consumed for PCI VGA device */
|
||||
/* reserve what device model consumed for PCI VGA device */
|
||||
|
||||
DWordMemory (ResourceConsumer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
|
||||
0x00000000,
|
||||
@@ -146,9 +161,9 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
})
|
||||
Return (PRT0)
|
||||
}
|
||||
Name(BUFA, ResourceTemplate() {
|
||||
Name(BUFA, ResourceTemplate() {
|
||||
IRQ(Level, ActiveLow, Shared) {
|
||||
3,4,5,6,7,10,11,12,14,15}
|
||||
3,4,5,6,7,10,11,12,14,15}
|
||||
})
|
||||
|
||||
Name(BUFB, Buffer(){
|
||||
@@ -156,7 +171,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
0x79, 0})
|
||||
|
||||
CreateWordField(BUFB, 0x01, IRQV)
|
||||
|
||||
|
||||
Name(BUFC, Buffer(){
|
||||
5, 7, 10, 11
|
||||
})
|
||||
@@ -165,17 +180,17 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
CreateByteField(BUFC, 0x01, PIQB)
|
||||
CreateByteField(BUFC, 0x01, PIQC)
|
||||
CreateByteField(BUFC, 0x01, PIQD)
|
||||
|
||||
Device(LNKA) {
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
|
||||
Device(LNKA) {
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 1)
|
||||
Method(_STA, 0) {
|
||||
And(PIRA, 0x80, Local0)
|
||||
If(LEqual(Local0, 0x80)) {
|
||||
Return(0x09)
|
||||
Return(0x09)
|
||||
}
|
||||
Else {
|
||||
Return(0x0B)
|
||||
Return(0x0B)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,34 +204,34 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
}
|
||||
|
||||
Method(_CRS) {
|
||||
And(PIRB, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
And(PIRB, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
}
|
||||
|
||||
Method(_SRS, 1) {
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRA)
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRA)
|
||||
} // Method(_SRS)
|
||||
}
|
||||
|
||||
Device(LNKB) {
|
||||
Name(_HID, EISAID("PNP0C0F"))
|
||||
Device(LNKB){
|
||||
Name(_HID, EISAID("PNP0C0F"))
|
||||
Name(_UID, 2)
|
||||
Method(_STA, 0) {
|
||||
And(PIRB, 0x80, Local0)
|
||||
If(LEqual(Local0, 0x80)) {
|
||||
Return(0x09)
|
||||
Return(0x09)
|
||||
}
|
||||
Else {
|
||||
Return(0x0B)
|
||||
Return(0x0B)
|
||||
}
|
||||
}
|
||||
|
||||
Method(_PRS) {
|
||||
Return(BUFA)
|
||||
Return(BUFA)
|
||||
} // Method(_PRS)
|
||||
|
||||
Method(_DIS) {
|
||||
@@ -225,35 +240,35 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
}
|
||||
|
||||
Method(_CRS) {
|
||||
And(PIRB, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
And(PIRB, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
} // Method(_CRS)
|
||||
|
||||
Method(_SRS, 1) {
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRB)
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRB)
|
||||
} // Method(_SRS)
|
||||
}
|
||||
|
||||
Device(LNKC) {
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Device(LNKC){
|
||||
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
|
||||
Name(_UID, 3)
|
||||
Method(_STA, 0) {
|
||||
And(PIRC, 0x80, Local0)
|
||||
And(PIRC, 0x80, Local0)
|
||||
If(LEqual(Local0, 0x80)) {
|
||||
Return(0x09)
|
||||
Return(0x09)
|
||||
}
|
||||
Else {
|
||||
Return(0x0B)
|
||||
Return(0x0B)
|
||||
}
|
||||
}
|
||||
|
||||
Method(_PRS) {
|
||||
Return(BUFA)
|
||||
} // Method(_PRS)
|
||||
Method(_PRS) {
|
||||
Return(BUFA)
|
||||
} // Method(_PRS)
|
||||
|
||||
Method(_DIS) {
|
||||
|
||||
@@ -261,91 +276,89 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
}
|
||||
|
||||
Method(_CRS) {
|
||||
And(PIRC, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
And(PIRC, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
} // Method(_CRS)
|
||||
|
||||
Method(_SRS, 1) {
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRC)
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRC)
|
||||
} // Method(_SRS)
|
||||
}
|
||||
|
||||
Device(LNKD) {
|
||||
Name(_HID, EISAID("PNP0C0F"))
|
||||
Device(LNKD) {
|
||||
Name(_HID, EISAID("PNP0C0F"))
|
||||
Name(_UID, 4)
|
||||
Method(_STA, 0) {
|
||||
And(PIRD, 0x80, Local0)
|
||||
If(LEqual(Local0, 0x80)) {
|
||||
Return(0x09)
|
||||
Return(0x09)
|
||||
}
|
||||
Else {
|
||||
Return(0x0B)
|
||||
Return(0x0B)
|
||||
}
|
||||
}
|
||||
|
||||
Method(_PRS) {
|
||||
Return(BUFA)
|
||||
} // Method(_PRS)
|
||||
Method(_PRS) {
|
||||
Return(BUFA)
|
||||
} // Method(_PRS)
|
||||
|
||||
Method(_DIS) {
|
||||
Or(PIRD, 0x80, PIRD)
|
||||
}
|
||||
|
||||
Method(_CRS) {
|
||||
And(PIRD, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
And(PIRD, 0x0f, Local0)
|
||||
ShiftLeft(0x1, Local0, IRQV)
|
||||
Return(BUFB)
|
||||
} // Method(_CRS)
|
||||
|
||||
Method(_SRS, 1) {
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRD)
|
||||
CreateWordField(ARG0, 0x01, IRQ1)
|
||||
FindSetRightBit(IRQ1, Local0)
|
||||
Decrement(Local0)
|
||||
Store(Local0, PIRD)
|
||||
} // Method(_SRS)
|
||||
}
|
||||
Method(_PRT,0) {
|
||||
If(PICD) {Return(PRTA)}
|
||||
Return (PRTP)
|
||||
} // end _PRT
|
||||
|
||||
|
||||
Name(PRTP, Package(){
|
||||
Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0}, // Slot 1, INTA
|
||||
Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0}, // Slot 1, INTB
|
||||
Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0}, // Slot 1, INTC
|
||||
Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0}, // Slot 1, INTD
|
||||
If(PICD) {Return(PRTA)}
|
||||
Return (PRTP)
|
||||
} // end _PRT
|
||||
|
||||
Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB
|
||||
Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC
|
||||
Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD
|
||||
Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA
|
||||
Name(PRTP, Package(){
|
||||
Package(){0x0000ffff, 0, \_SB.PCI0.LNKA, 0}, // Slot 1, INTA
|
||||
Package(){0x0000ffff, 1, \_SB.PCI0.LNKB, 0}, // Slot 1, INTB
|
||||
Package(){0x0000ffff, 2, \_SB.PCI0.LNKC, 0}, // Slot 1, INTC
|
||||
Package(){0x0000ffff, 3, \_SB.PCI0.LNKD, 0}, // Slot 1, INTD
|
||||
|
||||
Package(){0x0001ffff, 0, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB
|
||||
Package(){0x0001ffff, 1, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC
|
||||
Package(){0x0001ffff, 2, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD
|
||||
Package(){0x0001ffff, 3, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA
|
||||
|
||||
Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0}, // Slot 3, INTC
|
||||
Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0}, // Slot 3, INTD
|
||||
Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0}, // Slot 3, INTA
|
||||
Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0}, // Slot 3, INTB
|
||||
Package(){0x0002ffff, 0, \_SB.PCI0.LNKC, 0}, // Slot 3, INTC
|
||||
Package(){0x0002ffff, 1, \_SB.PCI0.LNKD, 0}, // Slot 3, INTD
|
||||
Package(){0x0002ffff, 2, \_SB.PCI0.LNKA, 0}, // Slot 3, INTA
|
||||
Package(){0x0002ffff, 3, \_SB.PCI0.LNKB, 0}, // Slot 3, INTB
|
||||
|
||||
Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD
|
||||
Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA
|
||||
Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB
|
||||
Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC
|
||||
Package(){0x0003ffff, 0, \_SB.PCI0.LNKD, 0}, // Slot 2, INTD
|
||||
Package(){0x0003ffff, 1, \_SB.PCI0.LNKA, 0}, // Slot 2, INTA
|
||||
Package(){0x0003ffff, 2, \_SB.PCI0.LNKB, 0}, // Slot 2, INTB
|
||||
Package(){0x0003ffff, 3, \_SB.PCI0.LNKC, 0}, // Slot 2, INTC
|
||||
|
||||
}
|
||||
)
|
||||
Name(PRTA, Package(){
|
||||
Package(){0x0001ffff, 0, 0, 5}, // Device 1, INTA
|
||||
Name(PRTA, Package(){
|
||||
Package(){0x0001ffff, 0, 0, 5}, // Device 1, INTA
|
||||
|
||||
Package(){0x0002ffff, 0, 0, 7}, // Device 2, INTA
|
||||
Package(){0x0002ffff, 0, 0, 7}, // Device 2, INTA
|
||||
|
||||
Package(){0x0003ffff, 0, 0, 10}, // Device 3, INTA
|
||||
Package(){0x0003ffff, 0, 0, 10}, // Device 3, INTA
|
||||
|
||||
Package(){0x0003ffff, 0, 0, 11}, // Device 4, INTA
|
||||
|
||||
Package(){0x0004ffff, 0, 0, 11}, // Device 4, INTA
|
||||
|
||||
}
|
||||
)
|
||||
@@ -354,22 +367,22 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
{
|
||||
Name (_ADR, 0x00000000) /* device id, PCI bus num, ... */
|
||||
|
||||
OperationRegion(PIRQ, PCI_Config, 0x60, 0x4)
|
||||
OperationRegion(PIRQ, PCI_Config, 0x60, 0x4)
|
||||
Scope(\) {
|
||||
Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
|
||||
Field (\_SB.PCI0.ISA.PIRQ, ByteAcc, NoLock, Preserve) {
|
||||
PIRA, 8,
|
||||
PIRB, 8,
|
||||
PIRC, 8,
|
||||
PIRD, 8
|
||||
}
|
||||
}
|
||||
}
|
||||
Device (SYSR)
|
||||
{
|
||||
Name (_HID, EisaId ("PNP0C02"))
|
||||
Name (_UID, 0x01)
|
||||
Name (CRS, ResourceTemplate ()
|
||||
{
|
||||
/* TODO: list hidden resources */
|
||||
/* TODO: list hidden resources */
|
||||
IO (Decode16, 0x0010, 0x0010, 0x00, 0x10)
|
||||
IO (Decode16, 0x0022, 0x0022, 0x00, 0x0C)
|
||||
IO (Decode16, 0x0030, 0x0030, 0x00, 0x10)
|
||||
@@ -417,7 +430,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 1, "INTEL","int-xen", 2006)
|
||||
IO (Decode16, 0x0089, 0x0089, 0x00, 0x03)
|
||||
IO (Decode16, 0x008F, 0x008F, 0x00, 0x01)
|
||||
IO (Decode16, 0x00C0, 0x00C0, 0x00, 0x20)
|
||||
IO (Decode16, 0x0480, 0x0480, 0x00, 0x10)
|
||||
IO (Decode16, 0x0480, 0x0480, 0x00, 0x10)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+270
-261
@@ -5,15 +5,15 @@
|
||||
* Copyright (C) 2000 - 2005 Intel Corporation
|
||||
* Supports ACPI Specification Revision 3.0
|
||||
*
|
||||
* Compilation of "acpi_dsdt.asl" - Mon Jun 12 22:33:41 2006
|
||||
* Compilation of "acpi_dsdt.asl" - Thu Aug 3 11:05:15 2006
|
||||
*
|
||||
* C source code output
|
||||
*
|
||||
*/
|
||||
unsigned char AmlCode[] =
|
||||
{
|
||||
0x44,0x53,0x44,0x54,0xC3,0x08,0x00,0x00, /* 00000000 "DSDT...." */
|
||||
0x01,0x0C,0x49,0x4E,0x54,0x45,0x4C,0x00, /* 00000008 "..INTEL." */
|
||||
0x44,0x53,0x44,0x54,0x0E,0x09,0x00,0x00, /* 00000000 "DSDT...." */
|
||||
0x01,0x03,0x49,0x4E,0x54,0x45,0x4C,0x00, /* 00000008 "..INTEL." */
|
||||
0x69,0x6E,0x74,0x2D,0x78,0x65,0x6E,0x00, /* 00000010 "int-xen." */
|
||||
0xD6,0x07,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
|
||||
0x13,0x05,0x05,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */
|
||||
@@ -34,264 +34,273 @@ unsigned char AmlCode[] =
|
||||
0x12,0x08,0x04,0x0A,0x07,0x0A,0x07,0x00, /* 00000098 "........" */
|
||||
0x00,0x08,0x50,0x49,0x43,0x44,0x00,0x14, /* 000000A0 "..PICD.." */
|
||||
0x0C,0x5F,0x50,0x49,0x43,0x01,0x70,0x68, /* 000000A8 "._PIC.ph" */
|
||||
0x50,0x49,0x43,0x44,0x10,0x4E,0x80,0x5F, /* 000000B0 "PICD.N._" */
|
||||
0x53,0x42,0x5F,0x5B,0x82,0x46,0x80,0x50, /* 000000B8 "SB_[.F.P" */
|
||||
0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000000C0 "CI0._HID" */
|
||||
0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x55, /* 000000C8 ".A...._U" */
|
||||
0x49,0x44,0x00,0x08,0x5F,0x41,0x44,0x52, /* 000000D0 "ID.._ADR" */
|
||||
0x00,0x08,0x5F,0x42,0x42,0x4E,0x00,0x5B, /* 000000D8 ".._BBN.[" */
|
||||
0x80,0x50,0x49,0x52,0x50,0x02,0x0A,0x3C, /* 000000E0 ".PIRP..<" */
|
||||
0x0A,0x10,0x5B,0x81,0x24,0x50,0x49,0x52, /* 000000E8 "..[.$PIR" */
|
||||
0x50,0x01,0x49,0x52,0x51,0x33,0x03,0x49, /* 000000F0 "P.IRQ3.I" */
|
||||
0x52,0x51,0x35,0x05,0x49,0x52,0x51,0x37, /* 000000F8 "RQ5.IRQ7" */
|
||||
0x07,0x49,0x52,0x51,0x39,0x09,0x49,0x52, /* 00000100 ".IRQ9.IR" */
|
||||
0x51,0x41,0x0A,0x49,0x52,0x51,0x42,0x0B, /* 00000108 "QA.IRQB." */
|
||||
0x14,0x48,0x0D,0x5F,0x43,0x52,0x53,0x00, /* 00000110 ".H._CRS." */
|
||||
0x08,0x50,0x52,0x54,0x30,0x11,0x46,0x0C, /* 00000118 ".PRT0.F." */
|
||||
0x0A,0xC2,0x88,0x0D,0x00,0x02,0x0F,0x00, /* 00000120 "........" */
|
||||
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00, /* 00000128 "........" */
|
||||
0x00,0x01,0x47,0x01,0xF8,0x0C,0xF8,0x0C, /* 00000130 "..G....." */
|
||||
0x01,0x08,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000138 "........" */
|
||||
0x00,0x00,0x00,0x00,0xF7,0x0C,0x00,0x00, /* 00000140 "........" */
|
||||
0xF8,0x0C,0x88,0x0D,0x00,0x01,0x0C,0x03, /* 00000148 "........" */
|
||||
0x00,0x00,0x00,0x0D,0xFF,0x0F,0x00,0x00, /* 00000150 "........" */
|
||||
0x00,0x03,0x88,0x0D,0x00,0x01,0x0D,0x03, /* 00000158 "........" */
|
||||
0x00,0x00,0x00,0xC0,0x1F,0xC0,0x00,0x00, /* 00000160 "........" */
|
||||
0x20,0x00,0x88,0x0D,0x00,0x01,0x0D,0x03, /* 00000168 " ......." */
|
||||
0x00,0x00,0x20,0xC0,0x3F,0xC0,0x00,0x00, /* 00000170 ".. .?..." */
|
||||
0x10,0x00,0x87,0x17,0x00,0x00,0x0C,0x02, /* 00000178 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00, /* 00000180 "........" */
|
||||
0xFF,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00, /* 00000188 "........" */
|
||||
0x00,0x00,0x03,0x00,0x87,0x17,0x00,0x00, /* 00000190 "........" */
|
||||
0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000198 "........" */
|
||||
0x00,0xF0,0xFF,0xFF,0xFF,0xF1,0x00,0x00, /* 000001A0 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x02,0x87,0x17, /* 000001A8 "........" */
|
||||
0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 000001B0 "........" */
|
||||
0x00,0x00,0x00,0xF2,0xFF,0x0F,0x00,0xF2, /* 000001B8 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, /* 000001C0 "........" */
|
||||
0x87,0x17,0x00,0x00,0x0D,0x03,0x00,0x00, /* 000001C8 "........" */
|
||||
0x00,0x00,0x00,0x10,0x00,0xF2,0x1F,0x10, /* 000001D0 "........" */
|
||||
0x00,0xF2,0x00,0x00,0x00,0x00,0x20,0x00, /* 000001D8 "...... ." */
|
||||
0x00,0x00,0x79,0x00,0xA4,0x50,0x52,0x54, /* 000001E0 "..y..PRT" */
|
||||
0x30,0x08,0x42,0x55,0x46,0x41,0x11,0x09, /* 000001E8 "0.BUFA.." */
|
||||
0x0A,0x06,0x23,0xF8,0xDC,0x18,0x79,0x00, /* 000001F0 "..#...y." */
|
||||
0x08,0x42,0x55,0x46,0x42,0x11,0x09,0x0A, /* 000001F8 ".BUFB..." */
|
||||
0x06,0x23,0x00,0x00,0x18,0x79,0x00,0x8B, /* 00000200 ".#...y.." */
|
||||
0x42,0x55,0x46,0x42,0x01,0x49,0x52,0x51, /* 00000208 "BUFB.IRQ" */
|
||||
0x56,0x08,0x42,0x55,0x46,0x43,0x11,0x07, /* 00000210 "V.BUFC.." */
|
||||
0x0A,0x04,0x05,0x07,0x0A,0x0B,0x8C,0x42, /* 00000218 ".......B" */
|
||||
0x55,0x46,0x43,0x01,0x50,0x49,0x51,0x41, /* 00000220 "UFC.PIQA" */
|
||||
0x8C,0x42,0x55,0x46,0x43,0x01,0x50,0x49, /* 00000228 ".BUFC.PI" */
|
||||
0x51,0x42,0x8C,0x42,0x55,0x46,0x43,0x01, /* 00000230 "QB.BUFC." */
|
||||
0x50,0x49,0x51,0x43,0x8C,0x42,0x55,0x46, /* 00000238 "PIQC.BUF" */
|
||||
0x43,0x01,0x50,0x49,0x51,0x44,0x5B,0x82, /* 00000240 "C.PIQD[." */
|
||||
0x48,0x08,0x4C,0x4E,0x4B,0x41,0x08,0x5F, /* 00000248 "H.LNKA._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 00000250 "HID.A..." */
|
||||
0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x1C, /* 00000258 "._UID..." */
|
||||
0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 00000260 "_STA.{PI" */
|
||||
0x52,0x41,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 00000268 "RA..`..." */
|
||||
0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 00000270 "`......." */
|
||||
0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 00000278 "....._PR" */
|
||||
0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 00000280 "S..BUFA." */
|
||||
0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000288 "._DIS.}P" */
|
||||
0x49,0x52,0x41,0x0A,0x80,0x50,0x49,0x52, /* 00000290 "IRA..PIR" */
|
||||
0x41,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 00000298 "A.._CRS." */
|
||||
0x7B,0x50,0x49,0x52,0x42,0x0A,0x0F,0x60, /* 000002A0 "{PIRB..`" */
|
||||
0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 000002A8 "y.`IRQV." */
|
||||
0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 000002B0 "BUFB.._S" */
|
||||
0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 000002B8 "RS..h.IR" */
|
||||
0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 000002C0 "Q1.IRQ1`" */
|
||||
0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x41, /* 000002C8 "v`p`PIRA" */
|
||||
0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x42, /* 000002D0 "[.I.LNKB" */
|
||||
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000002D8 "._HID.A." */
|
||||
0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 000002E0 "..._UID." */
|
||||
0x02,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000002E8 "..._STA." */
|
||||
0x7B,0x50,0x49,0x52,0x42,0x0A,0x80,0x60, /* 000002F0 "{PIRB..`" */
|
||||
0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000002F8 "...`...." */
|
||||
0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 00000300 "........" */
|
||||
0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 00000308 "_PRS..BU" */
|
||||
0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 00000310 "FA.._DIS" */
|
||||
0x00,0x7D,0x50,0x49,0x52,0x42,0x0A,0x80, /* 00000318 ".}PIRB.." */
|
||||
0x50,0x49,0x52,0x42,0x14,0x1A,0x5F,0x43, /* 00000320 "PIRB.._C" */
|
||||
0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x42, /* 00000328 "RS.{PIRB" */
|
||||
0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000330 "..`y.`IR" */
|
||||
0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000338 "QV.BUFB." */
|
||||
0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000340 "._SRS..h" */
|
||||
0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000348 ".IRQ1.IR" */
|
||||
0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000350 "Q1`v`p`P" */
|
||||
0x49,0x52,0x42,0x5B,0x82,0x49,0x08,0x4C, /* 00000358 "IRB[.I.L" */
|
||||
0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49,0x44, /* 00000360 "NKC._HID" */
|
||||
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000368 ".A...._U" */
|
||||
0x49,0x44,0x0A,0x03,0x14,0x1C,0x5F,0x53, /* 00000370 "ID...._S" */
|
||||
0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x43, /* 00000378 "TA.{PIRC" */
|
||||
0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 00000380 "..`...`." */
|
||||
0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 00000388 "........" */
|
||||
0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 00000390 "..._PRS." */
|
||||
0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 00000398 ".BUFA.._" */
|
||||
0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 000003A0 "DIS.}PIR" */
|
||||
0x43,0x0A,0x80,0x50,0x49,0x52,0x43,0x14, /* 000003A8 "C..PIRC." */
|
||||
0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 000003B0 "._CRS.{P" */
|
||||
0x49,0x52,0x43,0x0A,0x0F,0x60,0x79,0x01, /* 000003B8 "IRC..`y." */
|
||||
0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 000003C0 "`IRQV.BU" */
|
||||
0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 000003C8 "FB.._SRS" */
|
||||
0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 000003D0 "..h.IRQ1" */
|
||||
0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 000003D8 ".IRQ1`v`" */
|
||||
0x70,0x60,0x50,0x49,0x52,0x43,0x5B,0x82, /* 000003E0 "p`PIRC[." */
|
||||
0x49,0x08,0x4C,0x4E,0x4B,0x44,0x08,0x5F, /* 000003E8 "I.LNKD._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 000003F0 "HID.A..." */
|
||||
0x08,0x5F,0x55,0x49,0x44,0x0A,0x04,0x14, /* 000003F8 "._UID..." */
|
||||
0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,0x50, /* 00000400 "._STA.{P" */
|
||||
0x49,0x52,0x44,0x0A,0x80,0x60,0xA0,0x08, /* 00000408 "IRD..`.." */
|
||||
0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1, /* 00000410 ".`......" */
|
||||
0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50, /* 00000418 "......_P" */
|
||||
0x52,0x53,0x00,0xA4,0x42,0x55,0x46,0x41, /* 00000420 "RS..BUFA" */
|
||||
0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 00000428 ".._DIS.}" */
|
||||
0x50,0x49,0x52,0x44,0x0A,0x80,0x50,0x49, /* 00000430 "PIRD..PI" */
|
||||
0x52,0x44,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 00000438 "RD.._CRS" */
|
||||
0x00,0x7B,0x50,0x49,0x52,0x44,0x0A,0x0F, /* 00000440 ".{PIRD.." */
|
||||
0x60,0x79,0x01,0x60,0x49,0x52,0x51,0x56, /* 00000448 "`y.`IRQV" */
|
||||
0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,0x5F, /* 00000450 ".BUFB.._" */
|
||||
0x53,0x52,0x53,0x01,0x8B,0x68,0x01,0x49, /* 00000458 "SRS..h.I" */
|
||||
0x52,0x51,0x31,0x82,0x49,0x52,0x51,0x31, /* 00000460 "RQ1.IRQ1" */
|
||||
0x60,0x76,0x60,0x70,0x60,0x50,0x49,0x52, /* 00000468 "`v`p`PIR" */
|
||||
0x44,0x14,0x16,0x5F,0x50,0x52,0x54,0x00, /* 00000470 "D.._PRT." */
|
||||
0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4,0x50, /* 00000478 "..PICD.P" */
|
||||
0x52,0x54,0x41,0xA4,0x50,0x52,0x54,0x50, /* 00000480 "RTA.PRTP" */
|
||||
0x08,0x50,0x52,0x54,0x50,0x12,0x43,0x0E, /* 00000488 ".PRTP.C." */
|
||||
0x10,0x12,0x0B,0x04,0x0B,0xFF,0xFF,0x00, /* 00000490 "........" */
|
||||
0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0B,0x04, /* 00000498 "LNKA...." */
|
||||
0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B,0x42, /* 000004A0 "....LNKB" */
|
||||
0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A, /* 000004A8 "........" */
|
||||
0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0C, /* 000004B0 ".LNKC..." */
|
||||
0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C,0x4E, /* 000004B8 "......LN" */
|
||||
0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000004C0 "KD......" */
|
||||
0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B,0x42, /* 000004C8 "....LNKB" */
|
||||
0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01, /* 000004D0 "........" */
|
||||
0x00,0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000004D8 "..LNKC.." */
|
||||
0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 000004E0 "........" */
|
||||
0x02,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E, /* 000004E8 ".LNKD..." */
|
||||
0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03, /* 000004F0 "........" */
|
||||
0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 000004F8 "LNKA...." */
|
||||
0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C,0x4E, /* 00000500 "......LN" */
|
||||
0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000508 "KC......" */
|
||||
0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B,0x44, /* 00000510 "....LNKD" */
|
||||
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000518 "........" */
|
||||
0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00, /* 00000520 "...LNKA." */
|
||||
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000528 "........" */
|
||||
0x0A,0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000530 "..LNKB.." */
|
||||
0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00, /* 00000538 "........" */
|
||||
0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04, /* 00000540 "LNKD...." */
|
||||
0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C,0x4E, /* 00000548 "......LN" */
|
||||
0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000550 "KA......" */
|
||||
0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000558 ".....LNK" */
|
||||
0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000560 "B......." */
|
||||
0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43, /* 00000568 "....LNKC" */
|
||||
0x00,0x08,0x50,0x52,0x54,0x41,0x12,0x32, /* 00000570 "..PRTA.2" */
|
||||
0x04,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01, /* 00000578 "........" */
|
||||
0x00,0x00,0x00,0x0A,0x05,0x12,0x0B,0x04, /* 00000580 "........" */
|
||||
0x0C,0xFF,0xFF,0x02,0x00,0x00,0x00,0x0A, /* 00000588 "........" */
|
||||
0x07,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03, /* 00000590 "........" */
|
||||
0x00,0x00,0x00,0x0A,0x0A,0x12,0x0B,0x04, /* 00000598 "........" */
|
||||
0x0C,0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A, /* 000005A0 "........" */
|
||||
0x0B,0x5B,0x82,0x48,0x31,0x49,0x53,0x41, /* 000005A8 ".[.H1ISA" */
|
||||
0x5F,0x08,0x5F,0x41,0x44,0x52,0x00,0x5B, /* 000005B0 "_._ADR.[" */
|
||||
0x80,0x50,0x49,0x52,0x51,0x02,0x0A,0x60, /* 000005B8 ".PIRQ..`" */
|
||||
0x0A,0x04,0x10,0x2E,0x5C,0x00,0x5B,0x81, /* 000005C0 "....\.[." */
|
||||
0x29,0x5C,0x2F,0x04,0x5F,0x53,0x42,0x5F, /* 000005C8 ")\/._SB_" */
|
||||
0x50,0x43,0x49,0x30,0x49,0x53,0x41,0x5F, /* 000005D0 "PCI0ISA_" */
|
||||
0x50,0x49,0x52,0x51,0x01,0x50,0x49,0x52, /* 000005D8 "PIRQ.PIR" */
|
||||
0x41,0x08,0x50,0x49,0x52,0x42,0x08,0x50, /* 000005E0 "A.PIRB.P" */
|
||||
0x49,0x52,0x43,0x08,0x50,0x49,0x52,0x44, /* 000005E8 "IRC.PIRD" */
|
||||
0x08,0x5B,0x82,0x46,0x0B,0x53,0x59,0x53, /* 000005F0 ".[.F.SYS" */
|
||||
0x52,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 000005F8 "R._HID.A" */
|
||||
0xD0,0x0C,0x02,0x08,0x5F,0x55,0x49,0x44, /* 00000600 "...._UID" */
|
||||
0x01,0x08,0x43,0x52,0x53,0x5F,0x11,0x4E, /* 00000608 "..CRS_.N" */
|
||||
0x08,0x0A,0x8A,0x47,0x01,0x10,0x00,0x10, /* 00000610 "...G...." */
|
||||
0x00,0x00,0x10,0x47,0x01,0x22,0x00,0x22, /* 00000618 "...G."."" */
|
||||
0x00,0x00,0x0C,0x47,0x01,0x30,0x00,0x30, /* 00000620 "...G.0.0" */
|
||||
0x00,0x00,0x10,0x47,0x01,0x44,0x00,0x44, /* 00000628 "...G.D.D" */
|
||||
0x00,0x00,0x1C,0x47,0x01,0x62,0x00,0x62, /* 00000630 "...G.b.b" */
|
||||
0x00,0x00,0x02,0x47,0x01,0x65,0x00,0x65, /* 00000638 "...G.e.e" */
|
||||
0x00,0x00,0x0B,0x47,0x01,0x72,0x00,0x72, /* 00000640 "...G.r.r" */
|
||||
0x00,0x00,0x0E,0x47,0x01,0x80,0x00,0x80, /* 00000648 "...G...." */
|
||||
0x00,0x00,0x01,0x47,0x01,0x84,0x00,0x84, /* 00000650 "...G...." */
|
||||
0x00,0x00,0x03,0x47,0x01,0x88,0x00,0x88, /* 00000658 "...G...." */
|
||||
0x00,0x00,0x01,0x47,0x01,0x8C,0x00,0x8C, /* 00000660 "...G...." */
|
||||
0x00,0x00,0x03,0x47,0x01,0x90,0x00,0x90, /* 00000668 "...G...." */
|
||||
0x00,0x00,0x10,0x47,0x01,0xA2,0x00,0xA2, /* 00000670 "...G...." */
|
||||
0x00,0x00,0x1C,0x47,0x01,0xE0,0x00,0xE0, /* 00000678 "...G...." */
|
||||
0x00,0x00,0x10,0x47,0x01,0xA0,0x08,0xA0, /* 00000680 "...G...." */
|
||||
0x08,0x00,0x04,0x47,0x01,0xC0,0x0C,0xC0, /* 00000688 "...G...." */
|
||||
0x0C,0x00,0x10,0x47,0x01,0xD0,0x04,0xD0, /* 00000690 "...G...." */
|
||||
0x04,0x00,0x02,0x79,0x00,0x14,0x0B,0x5F, /* 00000698 "...y..._" */
|
||||
0x43,0x52,0x53,0x00,0xA4,0x43,0x52,0x53, /* 000006A0 "CRS..CRS" */
|
||||
0x5F,0x5B,0x82,0x2B,0x50,0x49,0x43,0x5F, /* 000006A8 "_[.+PIC_" */
|
||||
0x08,0x5F,0x48,0x49,0x44,0x0B,0x41,0xD0, /* 000006B0 "._HID.A." */
|
||||
0x08,0x5F,0x43,0x52,0x53,0x11,0x18,0x0A, /* 000006B8 "._CRS..." */
|
||||
0x15,0x47,0x01,0x20,0x00,0x20,0x00,0x01, /* 000006C0 ".G. . .." */
|
||||
0x02,0x47,0x01,0xA0,0x00,0xA0,0x00,0x01, /* 000006C8 ".G......" */
|
||||
0x02,0x22,0x04,0x00,0x79,0x00,0x5B,0x82, /* 000006D0 "."..y.[." */
|
||||
0x47,0x05,0x44,0x4D,0x41,0x30,0x08,0x5F, /* 000006D8 "G.DMA0._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x02,0x00, /* 000006E0 "HID.A..." */
|
||||
0x08,0x5F,0x43,0x52,0x53,0x11,0x41,0x04, /* 000006E8 "._CRS.A." */
|
||||
0x0A,0x3D,0x2A,0x10,0x04,0x47,0x01,0x00, /* 000006F0 ".=*..G.." */
|
||||
0x00,0x00,0x00,0x00,0x10,0x47,0x01,0x81, /* 000006F8 ".....G.." */
|
||||
0x00,0x81,0x00,0x00,0x03,0x47,0x01,0x87, /* 00000700 ".....G.." */
|
||||
0x00,0x87,0x00,0x00,0x01,0x47,0x01,0x89, /* 00000708 ".....G.." */
|
||||
0x00,0x89,0x00,0x00,0x03,0x47,0x01,0x8F, /* 00000710 ".....G.." */
|
||||
0x00,0x8F,0x00,0x00,0x01,0x47,0x01,0xC0, /* 00000718 ".....G.." */
|
||||
0x00,0xC0,0x00,0x00,0x20,0x47,0x01,0x80, /* 00000720 ".... G.." */
|
||||
0x04,0x80,0x04,0x00,0x10,0x79,0x00,0x5B, /* 00000728 ".....y.[" */
|
||||
0x82,0x25,0x54,0x4D,0x52,0x5F,0x08,0x5F, /* 00000730 ".%TMR_._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x01,0x00, /* 00000738 "HID.A..." */
|
||||
0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000740 "._CRS..." */
|
||||
0x0D,0x47,0x01,0x40,0x00,0x40,0x00,0x00, /* 00000748 ".G.@.@.." */
|
||||
0x04,0x22,0x01,0x00,0x79,0x00,0x5B,0x82, /* 00000750 "."..y.[." */
|
||||
0x25,0x52,0x54,0x43,0x5F,0x08,0x5F,0x48, /* 00000758 "%RTC_._H" */
|
||||
0x49,0x44,0x0C,0x41,0xD0,0x0B,0x00,0x08, /* 00000760 "ID.A...." */
|
||||
0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,0x0D, /* 00000768 "_CRS...." */
|
||||
0x47,0x01,0x70,0x00,0x70,0x00,0x00,0x02, /* 00000770 "G.p.p..." */
|
||||
0x22,0x00,0x01,0x79,0x00,0x5B,0x82,0x22, /* 00000778 ""..y.[."" */
|
||||
0x53,0x50,0x4B,0x52,0x08,0x5F,0x48,0x49, /* 00000780 "SPKR._HI" */
|
||||
0x44,0x0C,0x41,0xD0,0x08,0x00,0x08,0x5F, /* 00000788 "D.A...._" */
|
||||
0x43,0x52,0x53,0x11,0x0D,0x0A,0x0A,0x47, /* 00000790 "CRS....G" */
|
||||
0x01,0x61,0x00,0x61,0x00,0x00,0x01,0x79, /* 00000798 ".a.a...y" */
|
||||
0x00,0x5B,0x82,0x31,0x50,0x53,0x32,0x4D, /* 000007A0 ".[.1PS2M" */
|
||||
0x50,0x49,0x43,0x44,0x10,0x49,0x85,0x5F, /* 000000B0 "PICD.I._" */
|
||||
0x53,0x42,0x5F,0x5B,0x82,0x49,0x04,0x4D, /* 000000B8 "SB_[.I.M" */
|
||||
0x45,0x4D,0x30,0x08,0x5F,0x48,0x49,0x44, /* 000000C0 "EM0._HID" */
|
||||
0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43, /* 000000C8 ".A...._C" */
|
||||
0x52,0x53,0x11,0x33,0x0A,0x30,0x8A,0x2B, /* 000000D0 "RS.3.0.+" */
|
||||
0x00,0x00,0x0D,0x03,0x00,0x00,0x00,0x00, /* 000000D8 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */
|
||||
0x00,0x00,0x00,0x00,0xFF,0xFF,0x09,0x00, /* 000000E8 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000F0 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00, /* 000000F8 "........" */
|
||||
0x00,0x00,0x00,0x00,0x79,0x00,0x5B,0x82, /* 00000100 "....y.[." */
|
||||
0x46,0x80,0x50,0x43,0x49,0x30,0x08,0x5F, /* 00000108 "F.PCI0._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03, /* 00000110 "HID.A..." */
|
||||
0x08,0x5F,0x55,0x49,0x44,0x00,0x08,0x5F, /* 00000118 "._UID.._" */
|
||||
0x41,0x44,0x52,0x00,0x08,0x5F,0x42,0x42, /* 00000120 "ADR.._BB" */
|
||||
0x4E,0x00,0x5B,0x80,0x50,0x49,0x52,0x50, /* 00000128 "N.[.PIRP" */
|
||||
0x02,0x0A,0x3C,0x0A,0x10,0x5B,0x81,0x24, /* 00000130 "..<..[.$" */
|
||||
0x50,0x49,0x52,0x50,0x01,0x49,0x52,0x51, /* 00000138 "PIRP.IRQ" */
|
||||
0x33,0x03,0x49,0x52,0x51,0x35,0x05,0x49, /* 00000140 "3.IRQ5.I" */
|
||||
0x52,0x51,0x37,0x07,0x49,0x52,0x51,0x39, /* 00000148 "RQ7.IRQ9" */
|
||||
0x09,0x49,0x52,0x51,0x41,0x0A,0x49,0x52, /* 00000150 ".IRQA.IR" */
|
||||
0x51,0x42,0x0B,0x14,0x48,0x0D,0x5F,0x43, /* 00000158 "QB..H._C" */
|
||||
0x52,0x53,0x00,0x08,0x50,0x52,0x54,0x30, /* 00000160 "RS..PRT0" */
|
||||
0x11,0x46,0x0C,0x0A,0xC2,0x88,0x0D,0x00, /* 00000168 ".F......" */
|
||||
0x02,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF, /* 00000170 "........" */
|
||||
0x00,0x00,0x00,0x00,0x01,0x47,0x01,0xF8, /* 00000178 ".....G.." */
|
||||
0x0C,0xF8,0x0C,0x01,0x08,0x88,0x0D,0x00, /* 00000180 "........" */
|
||||
0x01,0x0C,0x03,0x00,0x00,0x00,0x00,0xF7, /* 00000188 "........" */
|
||||
0x0C,0x00,0x00,0xF8,0x0C,0x88,0x0D,0x00, /* 00000190 "........" */
|
||||
0x01,0x0C,0x03,0x00,0x00,0x00,0x0D,0xFF, /* 00000198 "........" */
|
||||
0x0F,0x00,0x00,0x00,0x03,0x88,0x0D,0x00, /* 000001A0 "........" */
|
||||
0x01,0x0D,0x03,0x00,0x00,0x00,0xC0,0x1F, /* 000001A8 "........" */
|
||||
0xC0,0x00,0x00,0x20,0x00,0x88,0x0D,0x00, /* 000001B0 "... ...." */
|
||||
0x01,0x0D,0x03,0x00,0x00,0x20,0xC0,0x3F, /* 000001B8 "..... .?" */
|
||||
0xC0,0x00,0x00,0x10,0x00,0x87,0x17,0x00, /* 000001C0 "........" */
|
||||
0x00,0x0C,0x02,0x00,0x00,0x00,0x00,0x00, /* 000001C8 "........" */
|
||||
0x00,0x0C,0x00,0xFF,0xFF,0x0F,0x00,0x00, /* 000001D0 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x87, /* 000001D8 "........" */
|
||||
0x17,0x00,0x00,0x0D,0x03,0x00,0x00,0x00, /* 000001E0 "........" */
|
||||
0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF, /* 000001E8 "........" */
|
||||
0xF1,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000001F0 "........" */
|
||||
0x02,0x87,0x17,0x00,0x00,0x0D,0x03,0x00, /* 000001F8 "........" */
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xF2,0xFF, /* 00000200 "........" */
|
||||
0x0F,0x00,0xF2,0x00,0x00,0x00,0x00,0x00, /* 00000208 "........" */
|
||||
0x10,0x00,0x00,0x87,0x17,0x00,0x00,0x0D, /* 00000210 "........" */
|
||||
0x03,0x00,0x00,0x00,0x00,0x00,0x10,0x00, /* 00000218 "........" */
|
||||
0xF2,0x1F,0x10,0x00,0xF2,0x00,0x00,0x00, /* 00000220 "........" */
|
||||
0x00,0x20,0x00,0x00,0x00,0x79,0x00,0xA4, /* 00000228 ". ...y.." */
|
||||
0x50,0x52,0x54,0x30,0x08,0x42,0x55,0x46, /* 00000230 "PRT0.BUF" */
|
||||
0x41,0x11,0x09,0x0A,0x06,0x23,0xF8,0xDC, /* 00000238 "A....#.." */
|
||||
0x18,0x79,0x00,0x08,0x42,0x55,0x46,0x42, /* 00000240 ".y..BUFB" */
|
||||
0x11,0x09,0x0A,0x06,0x23,0x00,0x00,0x18, /* 00000248 "....#..." */
|
||||
0x79,0x00,0x8B,0x42,0x55,0x46,0x42,0x01, /* 00000250 "y..BUFB." */
|
||||
0x49,0x52,0x51,0x56,0x08,0x42,0x55,0x46, /* 00000258 "IRQV.BUF" */
|
||||
0x43,0x11,0x07,0x0A,0x04,0x05,0x07,0x0A, /* 00000260 "C......." */
|
||||
0x0B,0x8C,0x42,0x55,0x46,0x43,0x01,0x50, /* 00000268 "..BUFC.P" */
|
||||
0x49,0x51,0x41,0x8C,0x42,0x55,0x46,0x43, /* 00000270 "IQA.BUFC" */
|
||||
0x01,0x50,0x49,0x51,0x42,0x8C,0x42,0x55, /* 00000278 ".PIQB.BU" */
|
||||
0x46,0x43,0x01,0x50,0x49,0x51,0x43,0x8C, /* 00000280 "FC.PIQC." */
|
||||
0x42,0x55,0x46,0x43,0x01,0x50,0x49,0x51, /* 00000288 "BUFC.PIQ" */
|
||||
0x44,0x5B,0x82,0x48,0x08,0x4C,0x4E,0x4B, /* 00000290 "D[.H.LNK" */
|
||||
0x41,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000298 "A._HID.A" */
|
||||
0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44, /* 000002A0 "...._UID" */
|
||||
0x01,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000002A8 "..._STA." */
|
||||
0x7B,0x50,0x49,0x52,0x41,0x0A,0x80,0x60, /* 000002B0 "{PIRA..`" */
|
||||
0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000002B8 "...`...." */
|
||||
0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 000002C0 "........" */
|
||||
0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 000002C8 "_PRS..BU" */
|
||||
0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 000002D0 "FA.._DIS" */
|
||||
0x00,0x7D,0x50,0x49,0x52,0x41,0x0A,0x80, /* 000002D8 ".}PIRA.." */
|
||||
0x50,0x49,0x52,0x41,0x14,0x1A,0x5F,0x43, /* 000002E0 "PIRA.._C" */
|
||||
0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x42, /* 000002E8 "RS.{PIRB" */
|
||||
0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 000002F0 "..`y.`IR" */
|
||||
0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 000002F8 "QV.BUFB." */
|
||||
0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000300 "._SRS..h" */
|
||||
0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000308 ".IRQ1.IR" */
|
||||
0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000310 "Q1`v`p`P" */
|
||||
0x49,0x52,0x41,0x5B,0x82,0x49,0x08,0x4C, /* 00000318 "IRA[.I.L" */
|
||||
0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44, /* 00000320 "NKB._HID" */
|
||||
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000328 ".A...._U" */
|
||||
0x49,0x44,0x0A,0x02,0x14,0x1C,0x5F,0x53, /* 00000330 "ID...._S" */
|
||||
0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x42, /* 00000338 "TA.{PIRB" */
|
||||
0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 00000340 "..`...`." */
|
||||
0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 00000348 "........" */
|
||||
0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 00000350 "..._PRS." */
|
||||
0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 00000358 ".BUFA.._" */
|
||||
0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 00000360 "DIS.}PIR" */
|
||||
0x42,0x0A,0x80,0x50,0x49,0x52,0x42,0x14, /* 00000368 "B..PIRB." */
|
||||
0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 00000370 "._CRS.{P" */
|
||||
0x49,0x52,0x42,0x0A,0x0F,0x60,0x79,0x01, /* 00000378 "IRB..`y." */
|
||||
0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 00000380 "`IRQV.BU" */
|
||||
0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000388 "FB.._SRS" */
|
||||
0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 00000390 "..h.IRQ1" */
|
||||
0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 00000398 ".IRQ1`v`" */
|
||||
0x70,0x60,0x50,0x49,0x52,0x42,0x5B,0x82, /* 000003A0 "p`PIRB[." */
|
||||
0x49,0x08,0x4C,0x4E,0x4B,0x43,0x08,0x5F, /* 000003A8 "I.LNKC._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F, /* 000003B0 "HID.A..." */
|
||||
0x08,0x5F,0x55,0x49,0x44,0x0A,0x03,0x14, /* 000003B8 "._UID..." */
|
||||
0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B,0x50, /* 000003C0 "._STA.{P" */
|
||||
0x49,0x52,0x43,0x0A,0x80,0x60,0xA0,0x08, /* 000003C8 "IRC..`.." */
|
||||
0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1, /* 000003D0 ".`......" */
|
||||
0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50, /* 000003D8 "......_P" */
|
||||
0x52,0x53,0x00,0xA4,0x42,0x55,0x46,0x41, /* 000003E0 "RS..BUFA" */
|
||||
0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 000003E8 ".._DIS.}" */
|
||||
0x50,0x49,0x52,0x43,0x0A,0x80,0x50,0x49, /* 000003F0 "PIRC..PI" */
|
||||
0x52,0x43,0x14,0x1A,0x5F,0x43,0x52,0x53, /* 000003F8 "RC.._CRS" */
|
||||
0x00,0x7B,0x50,0x49,0x52,0x43,0x0A,0x0F, /* 00000400 ".{PIRC.." */
|
||||
0x60,0x79,0x01,0x60,0x49,0x52,0x51,0x56, /* 00000408 "`y.`IRQV" */
|
||||
0xA4,0x42,0x55,0x46,0x42,0x14,0x1B,0x5F, /* 00000410 ".BUFB.._" */
|
||||
0x53,0x52,0x53,0x01,0x8B,0x68,0x01,0x49, /* 00000418 "SRS..h.I" */
|
||||
0x52,0x51,0x31,0x82,0x49,0x52,0x51,0x31, /* 00000420 "RQ1.IRQ1" */
|
||||
0x60,0x76,0x60,0x70,0x60,0x50,0x49,0x52, /* 00000428 "`v`p`PIR" */
|
||||
0x43,0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B, /* 00000430 "C[.I.LNK" */
|
||||
0x44,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000438 "D._HID.A" */
|
||||
0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44, /* 00000440 "...._UID" */
|
||||
0x0A,0x04,0x14,0x1C,0x5F,0x53,0x54,0x41, /* 00000448 "...._STA" */
|
||||
0x00,0x7B,0x50,0x49,0x52,0x44,0x0A,0x80, /* 00000450 ".{PIRD.." */
|
||||
0x60,0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4, /* 00000458 "`...`..." */
|
||||
0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14, /* 00000460 "........" */
|
||||
0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4,0x42, /* 00000468 "._PRS..B" */
|
||||
0x55,0x46,0x41,0x14,0x11,0x5F,0x44,0x49, /* 00000470 "UFA.._DI" */
|
||||
0x53,0x00,0x7D,0x50,0x49,0x52,0x44,0x0A, /* 00000478 "S.}PIRD." */
|
||||
0x80,0x50,0x49,0x52,0x44,0x14,0x1A,0x5F, /* 00000480 ".PIRD.._" */
|
||||
0x43,0x52,0x53,0x00,0x7B,0x50,0x49,0x52, /* 00000488 "CRS.{PIR" */
|
||||
0x44,0x0A,0x0F,0x60,0x79,0x01,0x60,0x49, /* 00000490 "D..`y.`I" */
|
||||
0x52,0x51,0x56,0xA4,0x42,0x55,0x46,0x42, /* 00000498 "RQV.BUFB" */
|
||||
0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000004A0 ".._SRS.." */
|
||||
0x68,0x01,0x49,0x52,0x51,0x31,0x82,0x49, /* 000004A8 "h.IRQ1.I" */
|
||||
0x52,0x51,0x31,0x60,0x76,0x60,0x70,0x60, /* 000004B0 "RQ1`v`p`" */
|
||||
0x50,0x49,0x52,0x44,0x14,0x16,0x5F,0x50, /* 000004B8 "PIRD.._P" */
|
||||
0x52,0x54,0x00,0xA0,0x0A,0x50,0x49,0x43, /* 000004C0 "RT...PIC" */
|
||||
0x44,0xA4,0x50,0x52,0x54,0x41,0xA4,0x50, /* 000004C8 "D.PRTA.P" */
|
||||
0x52,0x54,0x50,0x08,0x50,0x52,0x54,0x50, /* 000004D0 "RTP.PRTP" */
|
||||
0x12,0x43,0x0E,0x10,0x12,0x0B,0x04,0x0B, /* 000004D8 ".C......" */
|
||||
0xFF,0xFF,0x00,0x4C,0x4E,0x4B,0x41,0x00, /* 000004E0 "...LNKA." */
|
||||
0x12,0x0B,0x04,0x0B,0xFF,0xFF,0x01,0x4C, /* 000004E8 ".......L" */
|
||||
0x4E,0x4B,0x42,0x00,0x12,0x0C,0x04,0x0B, /* 000004F0 "NKB....." */
|
||||
0xFF,0xFF,0x0A,0x02,0x4C,0x4E,0x4B,0x43, /* 000004F8 "....LNKC" */
|
||||
0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF,0x0A, /* 00000500 "........" */
|
||||
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000508 ".LNKD..." */
|
||||
0x04,0x0C,0xFF,0xFF,0x01,0x00,0x00,0x4C, /* 00000510 ".......L" */
|
||||
0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000518 "NKB....." */
|
||||
0xFF,0xFF,0x01,0x00,0x01,0x4C,0x4E,0x4B, /* 00000520 ".....LNK" */
|
||||
0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000528 "C......." */
|
||||
0x01,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000530 "....LNKD" */
|
||||
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01, /* 00000538 "........" */
|
||||
0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000540 "...LNKA." */
|
||||
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000548 "........" */
|
||||
0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000550 ".LNKC..." */
|
||||
0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01,0x4C, /* 00000558 ".......L" */
|
||||
0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000560 "NKD....." */
|
||||
0xFF,0xFF,0x02,0x00,0x0A,0x02,0x4C,0x4E, /* 00000568 "......LN" */
|
||||
0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000570 "KA......" */
|
||||
0xFF,0x02,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000578 ".....LNK" */
|
||||
0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000580 "B......." */
|
||||
0x03,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000588 "...LNKD." */
|
||||
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000590 "........" */
|
||||
0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000598 ".LNKA..." */
|
||||
0x04,0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02, /* 000005A0 "........" */
|
||||
0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000005A8 "LNKB...." */
|
||||
0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x03,0x4C, /* 000005B0 ".......L" */
|
||||
0x4E,0x4B,0x43,0x00,0x08,0x50,0x52,0x54, /* 000005B8 "NKC..PRT" */
|
||||
0x41,0x12,0x32,0x04,0x12,0x0B,0x04,0x0C, /* 000005C0 "A.2....." */
|
||||
0xFF,0xFF,0x01,0x00,0x00,0x00,0x0A,0x05, /* 000005C8 "........" */
|
||||
0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 000005D0 "........" */
|
||||
0x00,0x00,0x0A,0x07,0x12,0x0B,0x04,0x0C, /* 000005D8 "........" */
|
||||
0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A,0x0A, /* 000005E0 "........" */
|
||||
0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 000005E8 "........" */
|
||||
0x00,0x00,0x0A,0x0B,0x5B,0x82,0x48,0x31, /* 000005F0 "....[.H1" */
|
||||
0x49,0x53,0x41,0x5F,0x08,0x5F,0x41,0x44, /* 000005F8 "ISA_._AD" */
|
||||
0x52,0x00,0x5B,0x80,0x50,0x49,0x52,0x51, /* 00000600 "R.[.PIRQ" */
|
||||
0x02,0x0A,0x60,0x0A,0x04,0x10,0x2E,0x5C, /* 00000608 "..`....\" */
|
||||
0x00,0x5B,0x81,0x29,0x5C,0x2F,0x04,0x5F, /* 00000610 ".[.)\/._" */
|
||||
0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x49, /* 00000618 "SB_PCI0I" */
|
||||
0x53,0x41,0x5F,0x50,0x49,0x52,0x51,0x01, /* 00000620 "SA_PIRQ." */
|
||||
0x50,0x49,0x52,0x41,0x08,0x50,0x49,0x52, /* 00000628 "PIRA.PIR" */
|
||||
0x42,0x08,0x50,0x49,0x52,0x43,0x08,0x50, /* 00000630 "B.PIRC.P" */
|
||||
0x49,0x52,0x44,0x08,0x5B,0x82,0x46,0x0B, /* 00000638 "IRD.[.F." */
|
||||
0x53,0x59,0x53,0x52,0x08,0x5F,0x48,0x49, /* 00000640 "SYSR._HI" */
|
||||
0x44,0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F, /* 00000648 "D.A...._" */
|
||||
0x55,0x49,0x44,0x01,0x08,0x43,0x52,0x53, /* 00000650 "UID..CRS" */
|
||||
0x5F,0x11,0x4E,0x08,0x0A,0x8A,0x47,0x01, /* 00000658 "_.N...G." */
|
||||
0x10,0x00,0x10,0x00,0x00,0x10,0x47,0x01, /* 00000660 "......G." */
|
||||
0x22,0x00,0x22,0x00,0x00,0x0C,0x47,0x01, /* 00000668 ""."...G." */
|
||||
0x30,0x00,0x30,0x00,0x00,0x10,0x47,0x01, /* 00000670 "0.0...G." */
|
||||
0x44,0x00,0x44,0x00,0x00,0x1C,0x47,0x01, /* 00000678 "D.D...G." */
|
||||
0x62,0x00,0x62,0x00,0x00,0x02,0x47,0x01, /* 00000680 "b.b...G." */
|
||||
0x65,0x00,0x65,0x00,0x00,0x0B,0x47,0x01, /* 00000688 "e.e...G." */
|
||||
0x72,0x00,0x72,0x00,0x00,0x0E,0x47,0x01, /* 00000690 "r.r...G." */
|
||||
0x80,0x00,0x80,0x00,0x00,0x01,0x47,0x01, /* 00000698 "......G." */
|
||||
0x84,0x00,0x84,0x00,0x00,0x03,0x47,0x01, /* 000006A0 "......G." */
|
||||
0x88,0x00,0x88,0x00,0x00,0x01,0x47,0x01, /* 000006A8 "......G." */
|
||||
0x8C,0x00,0x8C,0x00,0x00,0x03,0x47,0x01, /* 000006B0 "......G." */
|
||||
0x90,0x00,0x90,0x00,0x00,0x10,0x47,0x01, /* 000006B8 "......G." */
|
||||
0xA2,0x00,0xA2,0x00,0x00,0x1C,0x47,0x01, /* 000006C0 "......G." */
|
||||
0xE0,0x00,0xE0,0x00,0x00,0x10,0x47,0x01, /* 000006C8 "......G." */
|
||||
0xA0,0x08,0xA0,0x08,0x00,0x04,0x47,0x01, /* 000006D0 "......G." */
|
||||
0xC0,0x0C,0xC0,0x0C,0x00,0x10,0x47,0x01, /* 000006D8 "......G." */
|
||||
0xD0,0x04,0xD0,0x04,0x00,0x02,0x79,0x00, /* 000006E0 "......y." */
|
||||
0x14,0x0B,0x5F,0x43,0x52,0x53,0x00,0xA4, /* 000006E8 ".._CRS.." */
|
||||
0x43,0x52,0x53,0x5F,0x5B,0x82,0x2B,0x50, /* 000006F0 "CRS_[.+P" */
|
||||
0x49,0x43,0x5F,0x08,0x5F,0x48,0x49,0x44, /* 000006F8 "IC_._HID" */
|
||||
0x0B,0x41,0xD0,0x08,0x5F,0x43,0x52,0x53, /* 00000700 ".A.._CRS" */
|
||||
0x11,0x18,0x0A,0x15,0x47,0x01,0x20,0x00, /* 00000708 "....G. ." */
|
||||
0x20,0x00,0x01,0x02,0x47,0x01,0xA0,0x00, /* 00000710 " ...G..." */
|
||||
0xA0,0x00,0x01,0x02,0x22,0x04,0x00,0x79, /* 00000718 "...."..y" */
|
||||
0x00,0x5B,0x82,0x47,0x05,0x44,0x4D,0x41, /* 00000720 ".[.G.DMA" */
|
||||
0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000728 "0._HID.A" */
|
||||
0xD0,0x02,0x00,0x08,0x5F,0x43,0x52,0x53, /* 00000730 "...._CRS" */
|
||||
0x11,0x41,0x04,0x0A,0x3D,0x2A,0x10,0x04, /* 00000738 ".A..=*.." */
|
||||
0x47,0x01,0x00,0x00,0x00,0x00,0x00,0x10, /* 00000740 "G......." */
|
||||
0x47,0x01,0x81,0x00,0x81,0x00,0x00,0x03, /* 00000748 "G......." */
|
||||
0x47,0x01,0x87,0x00,0x87,0x00,0x00,0x01, /* 00000750 "G......." */
|
||||
0x47,0x01,0x89,0x00,0x89,0x00,0x00,0x03, /* 00000758 "G......." */
|
||||
0x47,0x01,0x8F,0x00,0x8F,0x00,0x00,0x01, /* 00000760 "G......." */
|
||||
0x47,0x01,0xC0,0x00,0xC0,0x00,0x00,0x20, /* 00000768 "G...... " */
|
||||
0x47,0x01,0x80,0x04,0x80,0x04,0x00,0x10, /* 00000770 "G......." */
|
||||
0x79,0x00,0x5B,0x82,0x25,0x54,0x4D,0x52, /* 00000778 "y.[.%TMR" */
|
||||
0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000780 "_._HID.A" */
|
||||
0xD0,0x01,0x00,0x08,0x5F,0x43,0x52,0x53, /* 00000788 "...._CRS" */
|
||||
0x11,0x10,0x0A,0x0D,0x47,0x01,0x40,0x00, /* 00000790 "....G.@." */
|
||||
0x40,0x00,0x00,0x04,0x22,0x01,0x00,0x79, /* 00000798 "@..."..y" */
|
||||
0x00,0x5B,0x82,0x25,0x52,0x54,0x43,0x5F, /* 000007A0 ".[.%RTC_" */
|
||||
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000007A8 "._HID.A." */
|
||||
0x0F,0x13,0x08,0x5F,0x43,0x49,0x44,0x0C, /* 000007B0 "..._CID." */
|
||||
0x41,0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53, /* 000007B8 "A....._S" */
|
||||
0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F, /* 000007C0 "TA....._" */
|
||||
0x43,0x52,0x53,0x11,0x08,0x0A,0x05,0x22, /* 000007C8 "CRS...."" */
|
||||
0x00,0x10,0x79,0x00,0x5B,0x82,0x42,0x04, /* 000007D0 "..y.[.B." */
|
||||
0x50,0x53,0x32,0x4B,0x08,0x5F,0x48,0x49, /* 000007D8 "PS2K._HI" */
|
||||
0x44,0x0C,0x41,0xD0,0x03,0x03,0x08,0x5F, /* 000007E0 "D.A...._" */
|
||||
0x43,0x49,0x44,0x0C,0x41,0xD0,0x03,0x0B, /* 000007E8 "CID.A..." */
|
||||
0x14,0x09,0x5F,0x53,0x54,0x41,0x00,0xA4, /* 000007F0 ".._STA.." */
|
||||
0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53,0x11, /* 000007F8 "..._CRS." */
|
||||
0x18,0x0A,0x15,0x47,0x01,0x60,0x00,0x60, /* 00000800 "...G.`.`" */
|
||||
0x00,0x00,0x01,0x47,0x01,0x64,0x00,0x64, /* 00000808 "...G.d.d" */
|
||||
0x00,0x00,0x01,0x22,0x02,0x00,0x79,0x00, /* 00000810 "..."..y." */
|
||||
0x5B,0x82,0x3A,0x46,0x44,0x43,0x30,0x08, /* 00000818 "[.:FDC0." */
|
||||
0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07, /* 00000820 "_HID.A.." */
|
||||
0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000828 "..._STA." */
|
||||
0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000830 "...._CRS" */
|
||||
0x11,0x1B,0x0A,0x18,0x47,0x01,0xF0,0x03, /* 00000838 "....G..." */
|
||||
0xF0,0x03,0x01,0x06,0x47,0x01,0xF7,0x03, /* 00000840 "....G..." */
|
||||
0xF7,0x03,0x01,0x01,0x22,0x40,0x00,0x2A, /* 00000848 "...."@.*" */
|
||||
0x04,0x00,0x79,0x00,0x5B,0x82,0x35,0x55, /* 00000850 "..y.[.5U" */
|
||||
0x41,0x52,0x31,0x08,0x5F,0x48,0x49,0x44, /* 00000858 "AR1._HID" */
|
||||
0x0C,0x41,0xD0,0x05,0x01,0x08,0x5F,0x55, /* 00000860 ".A...._U" */
|
||||
0x49,0x44,0x01,0x14,0x09,0x5F,0x53,0x54, /* 00000868 "ID..._ST" */
|
||||
0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000870 "A....._C" */
|
||||
0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000878 "RS....G." */
|
||||
0xF8,0x03,0xF8,0x03,0x01,0x08,0x22,0x10, /* 00000880 "......"." */
|
||||
0x00,0x79,0x00,0x5B,0x82,0x36,0x55,0x41, /* 00000888 ".y.[.6UA" */
|
||||
0x52,0x32,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000890 "R2._HID." */
|
||||
0x41,0xD0,0x05,0x01,0x08,0x5F,0x55,0x49, /* 00000898 "A...._UI" */
|
||||
0x44,0x0A,0x02,0x14,0x09,0x5F,0x53,0x54, /* 000008A0 "D...._ST" */
|
||||
0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 000008A8 "A....._C" */
|
||||
0x52,0x53,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 000008B0 "RS....G." */
|
||||
0xF8,0x02,0xF8,0x02,0x01,0x08,0x22,0x08, /* 000008B8 "......"." */
|
||||
0x00,0x79,0x00,
|
||||
0x0B,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 000007B0 "..._CRS." */
|
||||
0x10,0x0A,0x0D,0x47,0x01,0x70,0x00,0x70, /* 000007B8 "...G.p.p" */
|
||||
0x00,0x00,0x02,0x22,0x00,0x01,0x79,0x00, /* 000007C0 "..."..y." */
|
||||
0x5B,0x82,0x22,0x53,0x50,0x4B,0x52,0x08, /* 000007C8 "[."SPKR." */
|
||||
0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x08, /* 000007D0 "_HID.A.." */
|
||||
0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x0D, /* 000007D8 ".._CRS.." */
|
||||
0x0A,0x0A,0x47,0x01,0x61,0x00,0x61,0x00, /* 000007E0 "..G.a.a." */
|
||||
0x00,0x01,0x79,0x00,0x5B,0x82,0x31,0x50, /* 000007E8 "..y.[.1P" */
|
||||
0x53,0x32,0x4D,0x08,0x5F,0x48,0x49,0x44, /* 000007F0 "S2M._HID" */
|
||||
0x0C,0x41,0xD0,0x0F,0x13,0x08,0x5F,0x43, /* 000007F8 ".A...._C" */
|
||||
0x49,0x44,0x0C,0x41,0xD0,0x0F,0x13,0x14, /* 00000800 "ID.A...." */
|
||||
0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000808 "._STA..." */
|
||||
0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x08, /* 00000810 ".._CRS.." */
|
||||
0x0A,0x05,0x22,0x00,0x10,0x79,0x00,0x5B, /* 00000818 ".."..y.[" */
|
||||
0x82,0x42,0x04,0x50,0x53,0x32,0x4B,0x08, /* 00000820 ".B.PS2K." */
|
||||
0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x03, /* 00000828 "_HID.A.." */
|
||||
0x03,0x08,0x5F,0x43,0x49,0x44,0x0C,0x41, /* 00000830 ".._CID.A" */
|
||||
0xD0,0x03,0x0B,0x14,0x09,0x5F,0x53,0x54, /* 00000838 "....._ST" */
|
||||
0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000840 "A....._C" */
|
||||
0x52,0x53,0x11,0x18,0x0A,0x15,0x47,0x01, /* 00000848 "RS....G." */
|
||||
0x60,0x00,0x60,0x00,0x00,0x01,0x47,0x01, /* 00000850 "`.`...G." */
|
||||
0x64,0x00,0x64,0x00,0x00,0x01,0x22,0x02, /* 00000858 "d.d..."." */
|
||||
0x00,0x79,0x00,0x5B,0x82,0x3A,0x46,0x44, /* 00000860 ".y.[.:FD" */
|
||||
0x43,0x30,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000868 "C0._HID." */
|
||||
0x41,0xD0,0x07,0x00,0x14,0x09,0x5F,0x53, /* 00000870 "A....._S" */
|
||||
0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F, /* 00000878 "TA....._" */
|
||||
0x43,0x52,0x53,0x11,0x1B,0x0A,0x18,0x47, /* 00000880 "CRS....G" */
|
||||
0x01,0xF0,0x03,0xF0,0x03,0x01,0x06,0x47, /* 00000888 ".......G" */
|
||||
0x01,0xF7,0x03,0xF7,0x03,0x01,0x01,0x22, /* 00000890 "......."" */
|
||||
0x40,0x00,0x2A,0x04,0x00,0x79,0x00,0x5B, /* 00000898 "@.*..y.[" */
|
||||
0x82,0x35,0x55,0x41,0x52,0x31,0x08,0x5F, /* 000008A0 ".5UAR1._" */
|
||||
0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 000008A8 "HID.A..." */
|
||||
0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x09, /* 000008B0 "._UID..." */
|
||||
0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 000008B8 "_STA...." */
|
||||
0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 000008C0 "._CRS..." */
|
||||
0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03,0x01, /* 000008C8 ".G......" */
|
||||
0x08,0x22,0x10,0x00,0x79,0x00,0x5B,0x82, /* 000008D0 "."..y.[." */
|
||||
0x36,0x55,0x41,0x52,0x32,0x08,0x5F,0x48, /* 000008D8 "6UAR2._H" */
|
||||
0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 000008E0 "ID.A...." */
|
||||
0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x09, /* 000008E8 "_UID...." */
|
||||
0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 000008F0 "_STA...." */
|
||||
0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 000008F8 "._CRS..." */
|
||||
0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02,0x01, /* 00000900 ".G......" */
|
||||
0x08,0x22,0x08,0x00,0x79,0x00,
|
||||
};
|
||||
int DsdtLen=sizeof(AmlCode);
|
||||
@@ -42,12 +42,15 @@ OBJCOPY = objcopy
|
||||
CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
|
||||
LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
|
||||
|
||||
SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c
|
||||
OBJS = $(patsubst %.c,%.o,$(SRCS))
|
||||
|
||||
.PHONY: all
|
||||
all: hvmloader
|
||||
|
||||
hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c
|
||||
$(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c
|
||||
$(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o
|
||||
hvmloader: roms.h $(SRCS)
|
||||
$(CC) $(CFLAGS) -c $(SRCS)
|
||||
$(CC) $(LDFLAGS) -o hvmloader.tmp $(OBJS)
|
||||
$(OBJCOPY) hvmloader.tmp hvmloader
|
||||
rm -f hvmloader.tmp
|
||||
|
||||
|
||||
@@ -20,13 +20,11 @@
|
||||
|
||||
#include "../acpi/acpi2_0.h"
|
||||
#include "../acpi/acpi_madt.h"
|
||||
|
||||
#include "util.h"
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
|
||||
#define NULL ((void*)0)
|
||||
|
||||
extern int puts(const char *s);
|
||||
|
||||
static struct hvm_info_table *table = NULL;
|
||||
|
||||
static int validate_hvm_info(struct hvm_info_table *t)
|
||||
|
||||
@@ -23,15 +23,19 @@
|
||||
*/
|
||||
#include "roms.h"
|
||||
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
|
||||
#include "hypercall.h"
|
||||
#include "util.h"
|
||||
#include <xen/version.h>
|
||||
#include <xen/hvm/hvm_info_table.h>
|
||||
|
||||
/* memory map */
|
||||
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
|
||||
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
|
||||
#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
|
||||
#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
|
||||
|
||||
/* invoke SVM's paged realmode support */
|
||||
#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
|
||||
#define SVM_VMMCALL_RESET_TO_REALMODE 0x80000001
|
||||
|
||||
/*
|
||||
* C runtime start off
|
||||
@@ -75,79 +79,28 @@ extern int acpi_madt_update(unsigned char* acpi_start);
|
||||
extern void create_mp_tables(void);
|
||||
struct hvm_info_table *get_hvm_info_table(void);
|
||||
|
||||
static inline void
|
||||
outw(unsigned short addr, unsigned short val)
|
||||
{
|
||||
__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
|
||||
}
|
||||
|
||||
static inline void
|
||||
outb(unsigned short addr, unsigned char val)
|
||||
{
|
||||
__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
|
||||
}
|
||||
|
||||
static inline unsigned char
|
||||
inb(unsigned short addr)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
void *
|
||||
memcpy(void *dest, const void *src, unsigned n)
|
||||
{
|
||||
int t0, t1, t2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"cld\n"
|
||||
"rep; movsl\n"
|
||||
"testb $2,%b4\n"
|
||||
"je 1f\n"
|
||||
"movsw\n"
|
||||
"1: testb $1,%b4\n"
|
||||
"je 2f\n"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
|
||||
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
|
||||
: "memory"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
int
|
||||
puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
outb(0xE9, *s++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
cirrus_check(void)
|
||||
{
|
||||
outw(0x3C4, 0x9206);
|
||||
return inb(0x3C5) == 0x12;
|
||||
}
|
||||
|
||||
int
|
||||
vmmcall(int edi, int esi, int edx, int ecx, int ebx)
|
||||
static int
|
||||
vmmcall(int function, int edi, int esi, int edx, int ecx, int ebx)
|
||||
{
|
||||
int eax;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".byte 0x0F,0x01,0xD9"
|
||||
: "=a" (eax)
|
||||
: "a"(0x58454E00), /* XEN\0 key */
|
||||
: "a"(function),
|
||||
"b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
|
||||
);
|
||||
return eax;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
check_amd(void)
|
||||
{
|
||||
char id[12];
|
||||
@@ -162,6 +115,60 @@ check_amd(void)
|
||||
return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"cpuid"
|
||||
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
|
||||
: "0" (idx) );
|
||||
}
|
||||
|
||||
static void
|
||||
wrmsr(uint32_t idx, uint64_t v)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"wrmsr"
|
||||
: : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
|
||||
}
|
||||
|
||||
static void
|
||||
init_hypercalls(void)
|
||||
{
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
unsigned long i;
|
||||
char signature[13], number[13];
|
||||
xen_extraversion_t extraversion;
|
||||
|
||||
cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
*(uint32_t *)(signature + 0) = ebx;
|
||||
*(uint32_t *)(signature + 4) = ecx;
|
||||
*(uint32_t *)(signature + 8) = edx;
|
||||
signature[12] = '\0';
|
||||
|
||||
if (strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002)) {
|
||||
puts("FATAL: Xen hypervisor not detected\n");
|
||||
__asm__ __volatile__( "ud2" );
|
||||
}
|
||||
|
||||
cpuid(0x40000001, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
puts("Detected Xen v");
|
||||
puts(itoa(number, eax >> 16));
|
||||
puts(".");
|
||||
puts(itoa(number, eax & 0xffff));
|
||||
|
||||
cpuid(0x40000002, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
for (i = 0; i < eax; i++)
|
||||
wrmsr(ebx, HYPERCALL_PHYSICAL_ADDRESS + (i << 12) + i);
|
||||
|
||||
hypercall_xen_version(XENVER_extraversion, extraversion);
|
||||
puts(extraversion);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -169,6 +176,8 @@ main(void)
|
||||
|
||||
puts("HVM Loader\n");
|
||||
|
||||
init_hypercalls();
|
||||
|
||||
puts("Loading ROMBIOS ...\n");
|
||||
memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
|
||||
if (t->apic_enabled)
|
||||
@@ -200,7 +209,7 @@ main(void)
|
||||
if (check_amd()) {
|
||||
/* AMD implies this is SVM */
|
||||
puts("SVM go ...\n");
|
||||
vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
|
||||
vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0, 0);
|
||||
} else {
|
||||
puts("Loading VMXAssist ...\n");
|
||||
memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/******************************************************************************
|
||||
* hypercall.h
|
||||
*
|
||||
* Copyright (c) 2002-2006, K A Fraser
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation; or, when distributed
|
||||
* separately from the Linux kernel or incorporated into other
|
||||
* software packages, subject to the following license:
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this source file (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy, modify,
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __HVMLOADER_HYPERCALL_H__
|
||||
#define __HVMLOADER_HYPERCALL_H__
|
||||
|
||||
/*
|
||||
* NB. Hypercall address needs to be relative to a linkage symbol for
|
||||
* some version of ld to relocate the relative calls properly.
|
||||
* Keep this in sync with HYPERCALL_PHYSICAL_ADDRESS in hvmloader.c!
|
||||
*/
|
||||
#define hypercall_pa "_start - 0x80000"
|
||||
|
||||
#define __STR(x) #x
|
||||
#define STR(x) __STR(x)
|
||||
|
||||
#define _hypercall0(type, name) \
|
||||
({ \
|
||||
long __res; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res) \
|
||||
: \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall1(type, name, a1) \
|
||||
({ \
|
||||
long __res, __ign1; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res), "=b" (__ign1) \
|
||||
: "1" ((long)(a1)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall2(type, name, a1, a2) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
|
||||
: "1" ((long)(a1)), "2" ((long)(a2)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall3(type, name, a1, a2, a3) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3) \
|
||||
: "1" ((long)(a1)), "2" ((long)(a2)), \
|
||||
"3" ((long)(a3)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall4(type, name, a1, a2, a3, a4) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3, __ign4; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3), "=S" (__ign4) \
|
||||
: "1" ((long)(a1)), "2" ((long)(a2)), \
|
||||
"3" ((long)(a3)), "4" ((long)(a4)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
|
||||
asm volatile ( \
|
||||
"call "hypercall_pa" + " STR(__HYPERVISOR_##name * 32) \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
|
||||
: "1" ((long)(a1)), "2" ((long)(a2)), \
|
||||
"3" ((long)(a3)), "4" ((long)(a4)), \
|
||||
"5" ((long)(a5)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
static inline int
|
||||
hypercall_sched_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_memory_op(
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, memory_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_multicall(
|
||||
void *call_list, int nr_calls)
|
||||
{
|
||||
return _hypercall2(int, multicall, call_list, nr_calls);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_event_channel_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, event_channel_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_xen_version(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, xen_version, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_console_io(
|
||||
int cmd, int count, char *str)
|
||||
{
|
||||
return _hypercall3(int, console_io, cmd, count, str);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_vm_assist(
|
||||
unsigned int cmd, unsigned int type)
|
||||
{
|
||||
return _hypercall2(int, vm_assist, cmd, type);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_vcpu_op(
|
||||
int cmd, int vcpuid, void *extra_args)
|
||||
{
|
||||
return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hypercall_hvm_op(
|
||||
int cmd, void *arg)
|
||||
{
|
||||
return _hypercall2(int, hvm_op, cmd, arg);
|
||||
}
|
||||
|
||||
#endif /* __HVMLOADER_HYPERCALL_H__ */
|
||||
@@ -93,7 +93,8 @@ typedef signed long int64_t;
|
||||
|
||||
#define INTR_MAX_NR 16
|
||||
|
||||
extern int puts(const char *); /* for printing */
|
||||
#include "util.h"
|
||||
|
||||
extern int get_vcpu_nr(void); /* for the guest's VCPU count */
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* util.c: Helper library functions for HVMLoader.
|
||||
*
|
||||
* Leendert van Doorn, leendert@watson.ibm.com
|
||||
* Copyright (c) 2005, International Business Machines Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*/
|
||||
|
||||
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
|
||||
#include "util.h"
|
||||
|
||||
void outw(uint16_t addr, uint16_t val)
|
||||
{
|
||||
__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
|
||||
}
|
||||
|
||||
void outb(uint16_t addr, uint8_t val)
|
||||
{
|
||||
__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
|
||||
}
|
||||
|
||||
uint8_t inb(uint16_t addr)
|
||||
{
|
||||
uint8_t val;
|
||||
__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
|
||||
return val;
|
||||
}
|
||||
|
||||
char *itoa(char *a, unsigned int i)
|
||||
{
|
||||
unsigned int _i = i, x = 0;
|
||||
|
||||
do {
|
||||
x++;
|
||||
_i /= 10;
|
||||
} while (_i != 0);
|
||||
|
||||
a += x;
|
||||
*a-- = '\0';
|
||||
|
||||
do {
|
||||
*a-- = (i % 10) + '0';
|
||||
i /= 10;
|
||||
} while (i != 0);
|
||||
|
||||
return a + 1;
|
||||
}
|
||||
|
||||
int strcmp(const char *cs, const char *ct)
|
||||
{
|
||||
signed char res;
|
||||
|
||||
while (((res = *cs - *ct++) == 0) && (*cs++ != '\0'))
|
||||
continue;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, unsigned n)
|
||||
{
|
||||
int t0, t1, t2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"cld\n"
|
||||
"rep; movsl\n"
|
||||
"testb $2,%b4\n"
|
||||
"je 1f\n"
|
||||
"movsw\n"
|
||||
"1: testb $1,%b4\n"
|
||||
"je 2f\n"
|
||||
"movsb\n"
|
||||
"2:"
|
||||
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
|
||||
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
|
||||
: "memory"
|
||||
);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void puts(const char *s)
|
||||
{
|
||||
while (*s)
|
||||
outb(0xE9, *s++);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef __HVMLOADER_UTIL_H__
|
||||
#define __HVMLOADER_UTIL_H__
|
||||
|
||||
/* I/O output */
|
||||
void outw(uint16_t addr, uint16_t val);
|
||||
void outb(uint16_t addr, uint8_t val);
|
||||
|
||||
/* I/O input */
|
||||
uint8_t inb(uint16_t addr);
|
||||
|
||||
/* String and memory functions */
|
||||
int strcmp(const char *cs, const char *ct);
|
||||
void *memcpy(void *dest, const void *src, unsigned n);
|
||||
char *itoa(char *a, unsigned int i);
|
||||
|
||||
/* Debug output */
|
||||
void puts(const char *s);
|
||||
|
||||
#endif /* __HVMLOADER_UTIL_H__ */
|
||||
@@ -52,6 +52,31 @@ char *states[] = {
|
||||
static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define PT_ENTRY_PRESENT 0x1
|
||||
|
||||
static unsigned
|
||||
guest_linear_to_real(unsigned long base, unsigned off)
|
||||
{
|
||||
unsigned int gcr3 = oldctx.cr3;
|
||||
unsigned int l1_mfn;
|
||||
unsigned int l0_mfn;
|
||||
|
||||
if (!(oldctx.cr0 & CR0_PG))
|
||||
return base + off;
|
||||
|
||||
l1_mfn = ((unsigned int *)gcr3)[(base >> 22) & 0x3ff ];
|
||||
if (!(l1_mfn & PT_ENTRY_PRESENT))
|
||||
panic("l2 entry not present\n");
|
||||
l1_mfn = l1_mfn & 0xfffff000 ;
|
||||
|
||||
l0_mfn = ((unsigned int *)l1_mfn)[(base >> 12) & 0x3ff];
|
||||
if (!(l0_mfn & PT_ENTRY_PRESENT))
|
||||
panic("l1 entry not present\n");
|
||||
l0_mfn = l0_mfn & 0xfffff000;
|
||||
|
||||
return l0_mfn + off + (base & 0xfff);
|
||||
}
|
||||
|
||||
static unsigned
|
||||
address(struct regs *regs, unsigned seg, unsigned off)
|
||||
{
|
||||
@@ -70,7 +95,7 @@ address(struct regs *regs, unsigned seg, unsigned off)
|
||||
(mode == VM86_REAL_TO_PROTECTED && regs->cs == seg))
|
||||
return ((seg & 0xFFFF) << 4) + off;
|
||||
|
||||
entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3];
|
||||
entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 0))[seg >> 3];
|
||||
entry_high = entry >> 32;
|
||||
entry_low = entry & 0xFFFFFFFF;
|
||||
|
||||
@@ -94,7 +119,7 @@ void
|
||||
trace(struct regs *regs, int adjust, char *fmt, ...)
|
||||
{
|
||||
unsigned off = regs->eip - adjust;
|
||||
va_list ap;
|
||||
va_list ap;
|
||||
|
||||
if ((traceset & (1 << mode)) &&
|
||||
(mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) {
|
||||
@@ -755,7 +780,7 @@ load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes
|
||||
return 1;
|
||||
}
|
||||
|
||||
entry = ((unsigned long long *) oldctx.gdtr_base)[sel >> 3];
|
||||
entry = ((unsigned long long *) guest_linear_to_real(oldctx.gdtr_base, 0))[sel >> 3];
|
||||
|
||||
/* Check the P bit first */
|
||||
if (!((entry >> (15+32)) & 0x1) && sel != 0)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
D/audio////
|
||||
D/hw////
|
||||
D/linux-user////
|
||||
D/pc-bios////
|
||||
D/slirp////
|
||||
D/target-arm////
|
||||
D/target-i386////
|
||||
D/target-ppc////
|
||||
D/target-sparc////
|
||||
D/tests////
|
||||
D/fpu////
|
||||
D/keymaps////
|
||||
D/target-mips////
|
||||
D/target-sh4////
|
||||
/.cvsignore/1.14/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/COPYING/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/COPYING.LIB/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/Changelog/1.121/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/LICENSE/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/Makefile/1.104/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/Makefile.target/1.121/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/README/1.12/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/README.distrib/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/TODO/1.39/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/VERSION/1.29/Sun Aug 6 01:03:44 2006//Trelease_0_8_2
|
||||
/a.out.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/aes.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/aes.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/alpha-dis.c/1.3/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/alpha.ld/1.1/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/arm-dis.c/1.3/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/arm.ld/1.1/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block-bochs.c/1.1/Sun Aug 6 00:55:02 2006//Trelease_0_8_2
|
||||
/block-cloop.c/1.3/Sun Aug 6 00:55:02 2006//Trelease_0_8_2
|
||||
/block-cow.c/1.6/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block-dmg.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/block-qcow.c/1.7/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block-vmdk.c/1.8/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block-vpc.c/1.3/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block-vvfat.c/1.6/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block.c/1.28/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/block_int.h/1.5/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/bswap.h/1.5/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/cocoa.m/1.10/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/configure/1.110/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/console.c/1.8/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/cpu-all.h/1.57/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/cpu-defs.h/1.16/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/cpu-exec.c/1.83/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/dis-asm.h/1.11/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/disas.c/1.31/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/disas.h/1.7/Sun Aug 6 00:55:03 2006//Trelease_0_8_2
|
||||
/dyngen-exec.h/1.29/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/dyngen-op.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/dyngen.c/1.45/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/dyngen.h/1.11/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/elf.h/1.7/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/elf_ops.h/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/exec-all.h/1.48/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/exec.c/1.82/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/gdbstub.c/1.40/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/gdbstub.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/i386-dis.c/1.5/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/i386-vl.ld/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/i386.ld/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/ia64.ld/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/keymaps.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/kqemu.c/1.12/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/kqemu.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/linux-2.6.9-qemu-fast.patch/1.1/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/loader.c/1.3/Sun Aug 6 01:03:45 2006//Trelease_0_8_2
|
||||
/m68k-dis.c/1.1/Sun Aug 6 01:03:46 2006//Trelease_0_8_2
|
||||
/m68k.ld/1.1/Sun Aug 6 01:03:46 2006//Trelease_0_8_2
|
||||
/mips-dis.c/1.4/Sun Aug 6 01:03:47 2006//Trelease_0_8_2
|
||||
/monitor.c/1.54/Sun Aug 6 01:03:47 2006//Trelease_0_8_2
|
||||
/osdep.c/1.11/Sun Aug 6 01:03:47 2006//Trelease_0_8_2
|
||||
/osdep.h/1.6/Sun Aug 6 01:03:47 2006//Trelease_0_8_2
|
||||
/ppc-dis.c/1.7/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/ppc.ld/1.2/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/qemu-binfmt-conf.sh/1.4/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/qemu-doc.texi/1.100/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/qemu-img.c/1.10/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/qemu-img.texi/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/qemu-tech.texi/1.9/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/qemu_socket.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/readline.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/s390.ld/1.1/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/sdl.c/1.29/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/sdl_keysym.h/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/sh4-dis.c/1.1/Sun Aug 6 01:03:48 2006//Trelease_0_8_2
|
||||
/softmmu_exec.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/softmmu_header.h/1.13/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/softmmu_template.h/1.16/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/sparc-dis.c/1.3/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/sparc.ld/1.1/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/tap-win32.c/1.3/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/texi2pod.pl/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/thunk.c/1.6/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/thunk.h/1.13/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/translate-all.c/1.14/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/translate-op.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/usb-linux.c/1.8/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/vgafont.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
/vl.c/1.202/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/vl.h/1.136/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/vnc.c/1.7/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/vnc_keysym.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
|
||||
/vnchextile.h/1.2/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/x86_64.ld/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
|
||||
@@ -0,0 +1,7 @@
|
||||
A D/linux-user////
|
||||
A D/slirp////
|
||||
A D/target-arm////
|
||||
A D/target-mips////
|
||||
A D/target-ppc////
|
||||
A D/target-sh4////
|
||||
A D/target-sparc////
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
Nrelease_0_8_2
|
||||
@@ -11,6 +11,8 @@ ppc64-softmmu
|
||||
ppc-user
|
||||
qemu-doc.html
|
||||
qemu-tech.html
|
||||
qemu-doc.info
|
||||
qemu-tech.info
|
||||
qemu.1
|
||||
qemu.pod
|
||||
qemu-img.1
|
||||
@@ -25,5 +27,16 @@ mips-softmmu
|
||||
mipsel-softmmu
|
||||
mips-user
|
||||
mipsel-user
|
||||
.gdbinit
|
||||
sh4-user
|
||||
sh4-softmmu
|
||||
*.aux
|
||||
*.cp
|
||||
*.dvi
|
||||
*.fn
|
||||
*.ky
|
||||
*.log
|
||||
*.pg
|
||||
*.toc
|
||||
*.tp
|
||||
*.vr
|
||||
@@ -1,109 +0,0 @@
|
||||
D/audio////
|
||||
D/hw////
|
||||
D/linux-user////
|
||||
D/pc-bios////
|
||||
D/slirp////
|
||||
D/target-arm////
|
||||
D/target-i386////
|
||||
D/target-ppc////
|
||||
D/target-sparc////
|
||||
D/tests////
|
||||
D/fpu////
|
||||
D/keymaps////
|
||||
D/target-mips////
|
||||
/.cvsignore/1.13/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/COPYING/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/COPYING.LIB/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/Changelog/1.116/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/LICENSE/1.2/Sat Feb 12 14:45:23 2005//Trelease_0_8_1
|
||||
/Makefile/1.99/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/Makefile.target/1.107/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/README/1.12/Wed May 24 10:40:08 2006//Trelease_0_8_1
|
||||
/README.distrib/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/TODO/1.38/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/VERSION/1.28/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/a.out.h/1.2/Wed May 24 10:40:08 2006//Trelease_0_8_1
|
||||
/aes.c/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/aes.h/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/alpha-dis.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/alpha.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/arm-dis.c/1.3/Wed May 24 10:40:08 2006//Trelease_0_8_1
|
||||
/arm.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/block-bochs.c/1.1/Tue Apr 26 21:34:00 2005//Trelease_0_8_1
|
||||
/block-cloop.c/1.3/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/block-cow.c/1.5/Thu May 25 12:38:49 2006//Trelease_0_8_1
|
||||
/block-dmg.c/1.4/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/block-qcow.c/1.6/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/block-vmdk.c/1.7/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/block-vpc.c/1.2/Thu May 25 12:38:49 2006//Trelease_0_8_1
|
||||
/block-vvfat.c/1.5/Thu May 25 18:22:25 2006//Trelease_0_8_1
|
||||
/block.c/1.26/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/block_int.h/1.4/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/bswap.h/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/cocoa.m/1.8/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/configure/1.100/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/console.c/1.5/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/cpu-all.h/1.54/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/cpu-defs.h/1.15/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/cpu-exec.c/1.78/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/dis-asm.h/1.11/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/disas.c/1.30/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/disas.h/1.7/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/dyngen-exec.h/1.27/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/dyngen-op.h/1.1/Mon Jan 3 23:40:55 2005//Trelease_0_8_1
|
||||
/dyngen.c/1.42/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/dyngen.h/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/elf.h/1.6/Thu May 25 12:38:50 2006//Trelease_0_8_1
|
||||
/elf_ops.h/1.3/Tue May 2 20:54:12 2006//Trelease_0_8_1
|
||||
/exec-all.h/1.47/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/exec.c/1.79/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/gdbstub.c/1.36/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/gdbstub.h/1.2/Tue Apr 26 20:42:36 2005//Trelease_0_8_1
|
||||
/i386-dis.c/1.5/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/i386-vl.ld/1.3/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/i386.ld/1.2/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/ia64.ld/1.1/Thu Apr 7 22:20:28 2005//Trelease_0_8_1
|
||||
/keymaps.c/1.2/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/kqemu.c/1.10/Thu May 25 18:22:26 2006//Trelease_0_8_1
|
||||
/kqemu.h/1.1/Wed Feb 8 22:39:17 2006//Trelease_0_8_1
|
||||
/linux-2.6.9-qemu-fast.patch/1.1/Wed Dec 8 23:48:11 2004//Trelease_0_8_1
|
||||
/loader.c/1.2/Wed Apr 26 22:05:26 2006//Trelease_0_8_1
|
||||
/m68k-dis.c/1.1/Sun Nov 6 16:52:11 2005//Trelease_0_8_1
|
||||
/m68k.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/mips-dis.c/1.3/Thu May 25 18:22:28 2006//Trelease_0_8_1
|
||||
/monitor.c/1.48/Thu May 25 18:22:28 2006//Trelease_0_8_1
|
||||
/osdep.c/1.10/Wed May 24 10:40:10 2006//Trelease_0_8_1
|
||||
/osdep.h/1.5/Wed May 24 10:40:10 2006//Trelease_0_8_1
|
||||
/ppc-dis.c/1.7/Thu May 25 12:38:51 2006//Trelease_0_8_1
|
||||
/ppc.ld/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1
|
||||
/qemu-binfmt-conf.sh/1.4/Thu May 25 18:22:28 2006//Trelease_0_8_1
|
||||
/qemu-doc.texi/1.87/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/qemu-img.c/1.8/Thu May 25 12:38:51 2006//Trelease_0_8_1
|
||||
/qemu-img.texi/1.2/Thu May 25 12:38:51 2006//Trelease_0_8_1
|
||||
/qemu-tech.texi/1.9/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/qemu_socket.h/1.1/Sun Apr 30 22:53:25 2006//Trelease_0_8_1
|
||||
/readline.c/1.1/Tue May 23 19:16:56 2006//Trelease_0_8_1
|
||||
/s390.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/sdl.c/1.26/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/sdl_keysym.h/1.3/Tue Mar 1 21:43:41 2005//Trelease_0_8_1
|
||||
/sh4-dis.c/1.1/Thu Apr 27 21:05:14 2006//Trelease_0_8_1
|
||||
/softmmu_exec.h/1.1/Sun Oct 30 18:16:26 2005//Trelease_0_8_1
|
||||
/softmmu_header.h/1.13/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/softmmu_template.h/1.16/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/sparc-dis.c/1.2/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/sparc.ld/1.1/Wed May 17 14:47:01 2006//Trelease_0_8_1
|
||||
/tap-win32.c/1.2/Sun Feb 19 12:40:00 2006//Trelease_0_8_1
|
||||
/texi2pod.pl/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
|
||||
/thunk.c/1.6/Wed May 24 10:40:10 2006//Trelease_0_8_1
|
||||
/thunk.h/1.13/Wed May 17 14:47:02 2006//Trelease_0_8_1
|
||||
/translate-all.c/1.14/Thu May 25 18:22:29 2006//Trelease_0_8_1
|
||||
/translate-op.c/1.1/Sun Mar 13 16:53:06 2005//Trelease_0_8_1
|
||||
/usb-linux.c/1.4/Sat Mar 11 18:03:38 2006//Trelease_0_8_1
|
||||
/vgafont.h/1.1/Wed May 17 14:47:02 2006//Trelease_0_8_1
|
||||
/vl.c/1.184/Thu May 25 18:22:30 2006//Trelease_0_8_1
|
||||
/vl.h/1.116/Thu May 25 18:22:30 2006//Trelease_0_8_1
|
||||
/vnc.c/1.4/Mon May 1 21:44:22 2006//Trelease_0_8_1
|
||||
/vnc_keysym.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1
|
||||
/vnchextile.h/1.1/Sun Apr 30 21:28:36 2006//Trelease_0_8_1
|
||||
/x86_64.ld/1.1/Thu Jan 6 20:50:00 2005//Trelease_0_8_1
|
||||
D/target-sh4////
|
||||
@@ -1 +0,0 @@
|
||||
Nrelease_0_8_1
|
||||
@@ -1,3 +1,22 @@
|
||||
version 0.8.2:
|
||||
|
||||
- ACPI support
|
||||
- PC VGA BIOS fixes
|
||||
- switch to OpenBios for SPARC targets (Blue Swirl)
|
||||
- VNC server fixes
|
||||
- MIPS FPU support (Marius Groeger)
|
||||
- Solaris/SPARC host support (Ben Taylor)
|
||||
- PPC breakpoints and single stepping (Jason Wessel)
|
||||
- USB updates (Paul Brook)
|
||||
- UDP/TCP/telnet character devices (Jason Wessel)
|
||||
- Windows sparse file support (Frediano Ziglio)
|
||||
- RTL8139 NIC TCP segmentation offloading (Igor Kovalenko)
|
||||
- PCNET NIC support (Antony T Curtis)
|
||||
- Support for variable frequency host CPUs
|
||||
- Workaround for win32 SMP hosts
|
||||
- Support for AMD Flash memories (Jocelyn Mayer)
|
||||
- Audio capture to WAV files support (malc)
|
||||
|
||||
version 0.8.1:
|
||||
|
||||
- USB tablet support (Brad Campbell, Anthony Liguori)
|
||||
|
||||
+25
-6
@@ -1,12 +1,20 @@
|
||||
# Makefile for QEMU.
|
||||
|
||||
XEN_ROOT=../..
|
||||
include $(XEN_ROOT)/tools/Rules.mk
|
||||
|
||||
-include config-host.mak
|
||||
|
||||
.PHONY: all clean distclean dvi info install install-doc tar tarbin \
|
||||
speed test test2 html dvi info
|
||||
|
||||
CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
|
||||
ifdef CONFIG_DARWIN
|
||||
CFLAGS+= -mdynamic-no-pic
|
||||
endif
|
||||
ifeq ($(ARCH),sparc)
|
||||
CFLAGS+=-mcpu=ultrasparc
|
||||
endif
|
||||
LDFLAGS=-g
|
||||
LIBS=
|
||||
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
@@ -20,11 +28,15 @@ else
|
||||
DOCS=
|
||||
endif
|
||||
|
||||
all: $(DOCS)
|
||||
for d in $(TARGET_DIRS); do \
|
||||
$(MAKE) -C $$d $@ || exit 1 ; \
|
||||
done
|
||||
TOOLS=
|
||||
|
||||
all: $(TOOLS) $(DOCS) recurse-all
|
||||
|
||||
subdir-%:
|
||||
$(MAKE) -C $(subst subdir-,,$@) all
|
||||
|
||||
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
|
||||
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
|
||||
|
||||
@@ -42,6 +54,7 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
rm -f config-host.mak config-host.h $(DOCS)
|
||||
rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
|
||||
for d in $(TARGET_DIRS); do \
|
||||
rm -rf $$d || exit 1 ; \
|
||||
done
|
||||
@@ -63,7 +76,7 @@ install: all $(if $(BUILD_DOCS),install-doc)
|
||||
# $(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
|
||||
# mkdir -p "$(DESTDIR)$(datadir)"
|
||||
# for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
|
||||
# video.x proll.elf linux_boot.bin; do \
|
||||
# video.x openbios-sparc32 linux_boot.bin; do \
|
||||
# $(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
|
||||
# done
|
||||
ifndef CONFIG_WIN32
|
||||
@@ -106,6 +119,12 @@ qemu-img.1: qemu-img.texi
|
||||
perl -w $(SRC_PATH)/texi2pod.pl $< qemu-img.pod
|
||||
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
|
||||
|
||||
info: qemu-doc.info qemu-tech.info
|
||||
|
||||
dvi: qemu-doc.dvi qemu-tech.dvi
|
||||
|
||||
html: qemu-doc.html qemu-tech.html
|
||||
|
||||
FILE=qemu-$(shell cat VERSION)
|
||||
|
||||
# tar release (use 'make -k tar' on a checkouted tree)
|
||||
@@ -138,7 +157,7 @@ tarbin:
|
||||
$(datadir)/vgabios-cirrus.bin \
|
||||
$(datadir)/ppc_rom.bin \
|
||||
$(datadir)/video.x \
|
||||
$(datadir)/proll.elf \
|
||||
$(datadir)/openbios-sparc32 \
|
||||
$(datadir)/linux_boot.bin \
|
||||
$(docdir)/qemu-doc.html \
|
||||
$(docdir)/qemu-tech.html \
|
||||
|
||||
@@ -40,6 +40,11 @@ ifeq ($(TARGET_ARCH),arm)
|
||||
TARGET_ARCH2=armeb
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH),sh4)
|
||||
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
|
||||
TARGET_ARCH2=sh4eb
|
||||
endif
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH),mips)
|
||||
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
|
||||
TARGET_ARCH2=mipsel
|
||||
@@ -114,17 +119,24 @@ LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),sparc)
|
||||
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
|
||||
ifeq ($(CONFIG_SOLARIS),yes)
|
||||
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
|
||||
LDFLAGS+=-m32
|
||||
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
|
||||
else
|
||||
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
|
||||
LDFLAGS+=-m32
|
||||
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
|
||||
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
|
||||
# -static is used to avoid g1/g3 usage by the dynamic linker
|
||||
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),sparc64)
|
||||
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
|
||||
CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
|
||||
LDFLAGS+=-m64
|
||||
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
|
||||
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
|
||||
endif
|
||||
|
||||
@@ -186,7 +198,12 @@ LDFLAGS+=-p
|
||||
main.o: CFLAGS+=-p
|
||||
endif
|
||||
|
||||
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
|
||||
OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
|
||||
elfload.o linuxload.o
|
||||
ifdef TARGET_HAS_BFLT
|
||||
OBJS+= flatload.o
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH), i386)
|
||||
OBJS+= vm86.o
|
||||
endif
|
||||
@@ -323,25 +340,32 @@ endif
|
||||
ifdef CONFIG_ADLIB
|
||||
SOUND_HW += fmopl.o adlib.o
|
||||
endif
|
||||
AUDIODRV+= wavcapture.o
|
||||
|
||||
# SCSI layer
|
||||
VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
|
||||
|
||||
# USB layer
|
||||
VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o
|
||||
VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
|
||||
|
||||
# PCI network cards
|
||||
VL_OBJS+= ne2000.o rtl8139.o
|
||||
VL_OBJS+= ne2000.o rtl8139.o pcnet.o
|
||||
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
# Hardware support
|
||||
VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
||||
VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
|
||||
VL_OBJS+= cirrus_vga.o mixeng.o parallel.o
|
||||
VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
|
||||
VL_OBJS+= usb-uhci.o
|
||||
VL_OBJS+= piix4acpi.o
|
||||
VL_OBJS+= xenstore.o
|
||||
DEFINES += -DHAS_AUDIO
|
||||
endif
|
||||
ifeq ($(TARGET_BASE_ARCH), ppc)
|
||||
VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
||||
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
|
||||
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
|
||||
VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
|
||||
DEFINES += -DHAS_AUDIO
|
||||
endif
|
||||
ifeq ($(TARGET_ARCH), mips)
|
||||
@@ -350,7 +374,7 @@ VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
|
||||
endif
|
||||
ifeq ($(TARGET_BASE_ARCH), sparc)
|
||||
ifeq ($(TARGET_ARCH), sparc64)
|
||||
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o
|
||||
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
|
||||
VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
|
||||
VL_OBJS+= cirrus_vga.o parallel.o
|
||||
else
|
||||
@@ -361,6 +385,7 @@ endif
|
||||
ifeq ($(TARGET_BASE_ARCH), arm)
|
||||
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
|
||||
VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
|
||||
VL_OBJS+= versatile_pci.o
|
||||
endif
|
||||
ifeq ($(TARGET_BASE_ARCH), sh4)
|
||||
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
|
||||
@@ -398,7 +423,7 @@ endif
|
||||
ifndef CONFIG_DARWIN
|
||||
ifndef CONFIG_WIN32
|
||||
ifndef CONFIG_SOLARIS
|
||||
VL_LIBS=-lutil
|
||||
VL_LIBS=-lutil -lrt
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@@ -411,6 +436,11 @@ ifeq ($(ARCH),ia64)
|
||||
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),sparc64)
|
||||
VL_LDFLAGS+=-m64
|
||||
VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
|
||||
endif
|
||||
@@ -490,6 +520,13 @@ endif
|
||||
|
||||
loader.o: loader.c elf_ops.h
|
||||
|
||||
acpi.o: acpi.c acpi-dsdt.hex
|
||||
|
||||
ifdef BUILD_ACPI_TABLES
|
||||
$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
|
||||
iasl -tc -p $@ $<
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH), sh4)
|
||||
op.o: op.c op_mem.c cpu.h
|
||||
op_helper.o: op_helper.c exec.h cpu.h
|
||||
@@ -500,6 +537,8 @@ sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
|
||||
tc58128.o: tc58128.c
|
||||
endif
|
||||
|
||||
$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||
|
||||
|
||||
+2
-8
@@ -1,24 +1,20 @@
|
||||
short term:
|
||||
----------
|
||||
- support variable tsc freq
|
||||
- cycle counter for all archs
|
||||
- cpu_interrupt() win32/SMP fix
|
||||
- support variable tsc freq
|
||||
- USB host async
|
||||
- IDE async
|
||||
- debug option in 'configure' script + disable -fomit-frame-pointer
|
||||
- Precise VGA timings for old games/demos (malc patch)
|
||||
- merge PIC spurious interrupt patch
|
||||
- merge Solaris patch
|
||||
- warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?)
|
||||
- config file (at least for windows/Mac OS X)
|
||||
- commit message if execution of code in IO memory
|
||||
- update doc: PCI infos.
|
||||
- VNC patch + Synaptic patch.
|
||||
- basic VGA optimizations
|
||||
- physical memory cache (reduce qemu-fast address space size to about 32 MB)
|
||||
- better code fetch (different exception handling + CS.limit support)
|
||||
- do not resize vga if invalid size.
|
||||
- avoid looping if only exceptions
|
||||
- cycle counter for all archs
|
||||
- TLB code protection support for PPC
|
||||
- see openMosix Doc
|
||||
- disable SMC handling for ARM/SPARC/PPC (not finished)
|
||||
@@ -31,12 +27,10 @@ short term:
|
||||
- fix CCOP optimisation
|
||||
- fix all remaining thread lock issues (must put TBs in a specific invalid
|
||||
state, find a solution for tb_flush()).
|
||||
- fix arm fpu rounding (at least for float->integer conversions)
|
||||
|
||||
ppc specific:
|
||||
------------
|
||||
- TLB invalidate not needed if msr_pr changes
|
||||
- SPR_ENCODE() not useful
|
||||
- enable shift optimizations ?
|
||||
|
||||
linux-user specific:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
0.8.1
|
||||
0.8.2
|
||||
@@ -0,0 +1,20 @@
|
||||
/alsaaudio.c/1.7/Sun Aug 6 01:03:49 2006//Trelease_0_8_2
|
||||
/audio.c/1.14/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/audio.h/1.8/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/audio_int.h/1.10/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/audio_template.h/1.8/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/coreaudio.c/1.7/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/dsound_template.h/1.4/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/dsoundaudio.c/1.3/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/fmodaudio.c/1.7/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/mixeng.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/mixeng.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/mixeng_template.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/noaudio.c/1.7/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/ossaudio.c/1.11/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/rate_template.h/1.3/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/sdlaudio.c/1.8/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/sys-queue.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
|
||||
/wavaudio.c/1.8/Sun Aug 6 01:03:50 2006//Trelease_0_8_2
|
||||
/wavcapture.c/1.5/Sat Jul 22 17:06:44 2006//Trelease_0_8_2
|
||||
D
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
||||
Nrelease_0_8_2
|
||||
@@ -1,19 +0,0 @@
|
||||
/alsaaudio.c/1.5/Sun Nov 20 18:53:05 2005//Trelease_0_8_1
|
||||
/audio.c/1.9/Thu May 25 18:22:31 2006//Trelease_0_8_1
|
||||
/audio.h/1.5/Thu May 25 18:22:31 2006//Trelease_0_8_1
|
||||
/audio_int.h/1.7/Thu May 25 18:22:31 2006//Trelease_0_8_1
|
||||
/audio_template.h/1.4/Sun Nov 20 16:24:34 2005//Trelease_0_8_1
|
||||
/coreaudio.c/1.5/Sun Nov 20 18:53:42 2005//Trelease_0_8_1
|
||||
/dsound_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
|
||||
/dsoundaudio.c/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
|
||||
/fmodaudio.c/1.5/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/mixeng.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/mixeng.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/mixeng_template.h/1.2/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/noaudio.c/1.4/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/ossaudio.c/1.9/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/rate_template.h/1.2/Sat Nov 5 18:55:27 2005//Trelease_0_8_1
|
||||
/sdlaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
/sys-queue.h/1.1/Sun Oct 30 18:58:22 2005//Trelease_0_8_1
|
||||
/wavaudio.c/1.6/Thu May 25 18:22:32 2006//Trelease_0_8_1
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
Nrelease_0_8_1
|
||||
@@ -61,8 +61,8 @@ static struct {
|
||||
.size_in_usec_in = 1,
|
||||
.size_in_usec_out = 1,
|
||||
#endif
|
||||
.pcm_name_out = "hw:0,0",
|
||||
.pcm_name_in = "hw:0,0",
|
||||
.pcm_name_out = "default",
|
||||
.pcm_name_in = "default",
|
||||
#ifdef HIGH_LATENCY
|
||||
.buffer_size_in = 400000,
|
||||
.period_size_in = 400000 / 4,
|
||||
@@ -606,7 +606,6 @@ static int alsa_run_out (HWVoiceOut *hw)
|
||||
}
|
||||
}
|
||||
|
||||
mixeng_clear (src, written);
|
||||
rpos = (rpos + written) % hw->samples;
|
||||
samples -= written;
|
||||
len -= written;
|
||||
@@ -663,12 +662,9 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.nchannels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianness;
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
&obt_as,
|
||||
audio_need_to_swap_endian (endianness)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = obt.samples;
|
||||
|
||||
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
|
||||
@@ -752,12 +748,9 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.nchannels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianness;
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
&obt_as,
|
||||
audio_need_to_swap_endian (endianness)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = obt.samples;
|
||||
|
||||
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
|
||||
|
||||
+419
-29
@@ -29,6 +29,7 @@
|
||||
/* #define DEBUG_PLIVE */
|
||||
/* #define DEBUG_LIVE */
|
||||
/* #define DEBUG_OUT */
|
||||
/* #define DEBUG_CAPTURE */
|
||||
|
||||
#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
|
||||
|
||||
@@ -137,7 +138,7 @@ int audio_bug (const char *funcname, int cond)
|
||||
if (cond) {
|
||||
static int shown;
|
||||
|
||||
AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname);
|
||||
AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
|
||||
if (!shown) {
|
||||
shown = 1;
|
||||
AUD_log (NULL, "Save all your work and restart without audio\n");
|
||||
@@ -509,14 +510,28 @@ static void audio_print_settings (audsettings_t *as)
|
||||
AUD_log (NULL, "invalid(%d)", as->fmt);
|
||||
break;
|
||||
}
|
||||
|
||||
AUD_log (NULL, " endianness=");
|
||||
switch (as->endianness) {
|
||||
case 0:
|
||||
AUD_log (NULL, "little");
|
||||
break;
|
||||
case 1:
|
||||
AUD_log (NULL, "big");
|
||||
break;
|
||||
default:
|
||||
AUD_log (NULL, "invalid");
|
||||
break;
|
||||
}
|
||||
AUD_log (NULL, "\n");
|
||||
}
|
||||
|
||||
static int audio_validate_settigs (audsettings_t *as)
|
||||
static int audio_validate_settings (audsettings_t *as)
|
||||
{
|
||||
int invalid;
|
||||
|
||||
invalid = as->nchannels != 1 && as->nchannels != 2;
|
||||
invalid |= as->endianness != 0 && as->endianness != 1;
|
||||
|
||||
switch (as->fmt) {
|
||||
case AUD_FMT_S8:
|
||||
@@ -530,11 +545,7 @@ static int audio_validate_settigs (audsettings_t *as)
|
||||
}
|
||||
|
||||
invalid |= as->freq <= 0;
|
||||
|
||||
if (invalid) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return invalid ? -1 : 0;
|
||||
}
|
||||
|
||||
static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
|
||||
@@ -556,14 +567,11 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
|
||||
return info->freq == as->freq
|
||||
&& info->nchannels == as->nchannels
|
||||
&& info->sign == sign
|
||||
&& info->bits == bits;
|
||||
&& info->bits == bits
|
||||
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
|
||||
}
|
||||
|
||||
void audio_pcm_init_info (
|
||||
struct audio_pcm_info *info,
|
||||
audsettings_t *as,
|
||||
int swap_endian
|
||||
)
|
||||
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
|
||||
{
|
||||
int bits = 8, sign = 0;
|
||||
|
||||
@@ -587,7 +595,7 @@ void audio_pcm_init_info (
|
||||
info->shift = (as->nchannels == 2) + (bits == 16);
|
||||
info->align = (1 << info->shift) - 1;
|
||||
info->bytes_per_second = info->freq << info->shift;
|
||||
info->swap_endian = swap_endian;
|
||||
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
|
||||
}
|
||||
|
||||
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
@@ -597,11 +605,11 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
}
|
||||
|
||||
if (info->sign) {
|
||||
memset (buf, len << info->shift, 0x00);
|
||||
memset (buf, 0x00, len << info->shift);
|
||||
}
|
||||
else {
|
||||
if (info->bits == 8) {
|
||||
memset (buf, len << info->shift, 0x80);
|
||||
memset (buf, 0x80, len << info->shift);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
@@ -609,7 +617,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
int shift = info->nchannels - 1;
|
||||
short s = INT16_MAX;
|
||||
|
||||
if (info->swap_endian) {
|
||||
if (info->swap_endianness) {
|
||||
s = bswap16 (s);
|
||||
}
|
||||
|
||||
@@ -620,6 +628,143 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Capture
|
||||
*/
|
||||
static void noop_conv (st_sample_t *dst, const void *src,
|
||||
int samples, volume_t *vol)
|
||||
{
|
||||
(void) src;
|
||||
(void) dst;
|
||||
(void) samples;
|
||||
(void) vol;
|
||||
}
|
||||
|
||||
static CaptureVoiceOut *audio_pcm_capture_find_specific (
|
||||
AudioState *s,
|
||||
audsettings_t *as
|
||||
)
|
||||
{
|
||||
CaptureVoiceOut *cap;
|
||||
|
||||
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
|
||||
if (audio_pcm_info_eq (&cap->hw.info, as)) {
|
||||
return cap;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
|
||||
{
|
||||
struct capture_callback *cb;
|
||||
|
||||
#ifdef DEBUG_CAPTURE
|
||||
dolog ("notification %d sent\n", cmd);
|
||||
#endif
|
||||
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
|
||||
cb->ops.notify (cb->opaque, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled)
|
||||
{
|
||||
if (cap->hw.enabled != enabled) {
|
||||
audcnotification_e cmd;
|
||||
cap->hw.enabled = enabled;
|
||||
cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
|
||||
audio_notify_capture (cap, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
|
||||
{
|
||||
HWVoiceOut *hw = &cap->hw;
|
||||
SWVoiceOut *sw;
|
||||
int enabled = 0;
|
||||
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
if (sw->active) {
|
||||
enabled = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
audio_capture_maybe_changed (cap, enabled);
|
||||
}
|
||||
|
||||
static void audio_detach_capture (HWVoiceOut *hw)
|
||||
{
|
||||
SWVoiceCap *sc = hw->cap_head.lh_first;
|
||||
|
||||
while (sc) {
|
||||
SWVoiceCap *sc1 = sc->entries.le_next;
|
||||
SWVoiceOut *sw = &sc->sw;
|
||||
CaptureVoiceOut *cap = sc->cap;
|
||||
int was_active = sw->active;
|
||||
|
||||
if (sw->rate) {
|
||||
st_rate_stop (sw->rate);
|
||||
sw->rate = NULL;
|
||||
}
|
||||
|
||||
LIST_REMOVE (sw, entries);
|
||||
LIST_REMOVE (sc, entries);
|
||||
qemu_free (sc);
|
||||
if (was_active) {
|
||||
/* We have removed soft voice from the capture:
|
||||
this might have changed the overall status of the capture
|
||||
since this might have been the only active voice */
|
||||
audio_recalc_and_notify_capture (cap);
|
||||
}
|
||||
sc = sc1;
|
||||
}
|
||||
}
|
||||
|
||||
static int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
|
||||
{
|
||||
CaptureVoiceOut *cap;
|
||||
|
||||
audio_detach_capture (hw);
|
||||
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
|
||||
SWVoiceCap *sc;
|
||||
SWVoiceOut *sw;
|
||||
HWVoiceOut *hw_cap = &cap->hw;
|
||||
|
||||
sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc));
|
||||
if (!sc) {
|
||||
dolog ("Could not allocate soft capture voice (%zu bytes)\n",
|
||||
sizeof (*sc));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sc->cap = cap;
|
||||
sw = &sc->sw;
|
||||
sw->hw = hw_cap;
|
||||
sw->info = hw->info;
|
||||
sw->empty = 1;
|
||||
sw->active = hw->enabled;
|
||||
sw->conv = noop_conv;
|
||||
sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
|
||||
sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
|
||||
if (!sw->rate) {
|
||||
dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
|
||||
qemu_free (sw);
|
||||
return -1;
|
||||
}
|
||||
LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
|
||||
LIST_INSERT_HEAD (&hw->cap_head, sc, entries);
|
||||
#ifdef DEBUG_CAPTURE
|
||||
asprintf (&sw->name, "for %p %d,%d,%d",
|
||||
hw, sw->info.freq, sw->info.bits, sw->info.nchannels);
|
||||
dolog ("Added %s active = %d\n", sw->name, sw->active);
|
||||
#endif
|
||||
if (sw->active) {
|
||||
audio_capture_maybe_changed (cap, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hard voice (capture)
|
||||
*/
|
||||
@@ -796,6 +941,9 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
|
||||
}
|
||||
|
||||
if (live == hwsamples) {
|
||||
#ifdef DEBUG_OUT
|
||||
dolog ("%s is full %d\n", sw->name, live);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -914,19 +1062,14 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
|
||||
hw = sw->hw;
|
||||
if (sw->active != on) {
|
||||
SWVoiceOut *temp_sw;
|
||||
SWVoiceCap *sc;
|
||||
|
||||
if (on) {
|
||||
int total;
|
||||
|
||||
hw->pending_disable = 0;
|
||||
if (!hw->enabled) {
|
||||
hw->enabled = 1;
|
||||
hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
|
||||
}
|
||||
|
||||
if (sw->empty) {
|
||||
total = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hw->enabled) {
|
||||
@@ -940,6 +1083,13 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
|
||||
hw->pending_disable = nb_active == 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
sc->sw.active = hw->enabled;
|
||||
if (hw->enabled) {
|
||||
audio_capture_maybe_changed (sc->cap, 1);
|
||||
}
|
||||
}
|
||||
sw->active = on;
|
||||
}
|
||||
}
|
||||
@@ -997,7 +1147,7 @@ static int audio_get_avail (SWVoiceIn *sw)
|
||||
}
|
||||
|
||||
ldebug (
|
||||
"%s: get_avail live %d ret %lld\n",
|
||||
"%s: get_avail live %d ret %" PRId64 "\n",
|
||||
SW_NAME (sw),
|
||||
live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
|
||||
);
|
||||
@@ -1023,7 +1173,7 @@ static int audio_get_free (SWVoiceOut *sw)
|
||||
dead = sw->hw->samples - live;
|
||||
|
||||
#ifdef DEBUG_OUT
|
||||
dolog ("%s: get_free live %d dead %d ret %lld\n",
|
||||
dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",
|
||||
SW_NAME (sw),
|
||||
live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
|
||||
#endif
|
||||
@@ -1031,6 +1181,43 @@ static int audio_get_free (SWVoiceOut *sw)
|
||||
return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
|
||||
}
|
||||
|
||||
static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (hw->enabled) {
|
||||
SWVoiceCap *sc;
|
||||
|
||||
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
SWVoiceOut *sw = &sc->sw;
|
||||
int rpos2 = rpos;
|
||||
|
||||
n = samples;
|
||||
while (n) {
|
||||
int till_end_of_hw = hw->samples - rpos2;
|
||||
int to_write = audio_MIN (till_end_of_hw, n);
|
||||
int bytes = to_write << hw->info.shift;
|
||||
int written;
|
||||
|
||||
sw->buf = hw->mix_buf + rpos2;
|
||||
written = audio_pcm_sw_write (sw, NULL, bytes);
|
||||
if (written - bytes) {
|
||||
dolog ("Could not mix %d bytes into a capture "
|
||||
"buffer, mixed %d\n",
|
||||
bytes, written);
|
||||
break;
|
||||
}
|
||||
n -= to_write;
|
||||
rpos2 = (rpos2 + to_write) % hw->samples;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n = audio_MIN (samples, hw->samples - rpos);
|
||||
mixeng_clear (hw->mix_buf + rpos, n);
|
||||
mixeng_clear (hw->mix_buf, samples - n);
|
||||
}
|
||||
|
||||
static void audio_run_out (AudioState *s)
|
||||
{
|
||||
HWVoiceOut *hw = NULL;
|
||||
@@ -1038,7 +1225,7 @@ static void audio_run_out (AudioState *s)
|
||||
|
||||
while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
|
||||
int played;
|
||||
int live, free, nb_live, cleanup_required;
|
||||
int live, free, nb_live, cleanup_required, prev_rpos;
|
||||
|
||||
live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
|
||||
if (!nb_live) {
|
||||
@@ -1051,12 +1238,17 @@ static void audio_run_out (AudioState *s)
|
||||
}
|
||||
|
||||
if (hw->pending_disable && !nb_live) {
|
||||
SWVoiceCap *sc;
|
||||
#ifdef DEBUG_OUT
|
||||
dolog ("Disabling voice\n");
|
||||
#endif
|
||||
hw->enabled = 0;
|
||||
hw->pending_disable = 0;
|
||||
hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);
|
||||
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
sc->sw.active = 0;
|
||||
audio_recalc_and_notify_capture (sc->cap);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1072,6 +1264,7 @@ static void audio_run_out (AudioState *s)
|
||||
continue;
|
||||
}
|
||||
|
||||
prev_rpos = hw->rpos;
|
||||
played = hw->pcm_ops->run_out (hw);
|
||||
if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
|
||||
dolog ("hw->rpos=%d hw->samples=%d played=%d\n",
|
||||
@@ -1085,6 +1278,7 @@ static void audio_run_out (AudioState *s)
|
||||
|
||||
if (played) {
|
||||
hw->ts_helper += played;
|
||||
audio_capture_mix_and_clear (hw, prev_rpos, played);
|
||||
}
|
||||
|
||||
cleanup_required = 0;
|
||||
@@ -1115,15 +1309,18 @@ static void audio_run_out (AudioState *s)
|
||||
}
|
||||
|
||||
if (cleanup_required) {
|
||||
restart:
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
SWVoiceOut *sw1;
|
||||
|
||||
sw = hw->sw_head.lh_first;
|
||||
while (sw) {
|
||||
sw1 = sw->entries.le_next;
|
||||
if (!sw->active && !sw->callback.fn) {
|
||||
#ifdef DEBUG_PLIVE
|
||||
dolog ("Finishing with old voice\n");
|
||||
#endif
|
||||
audio_close_out (s, sw);
|
||||
goto restart; /* play it safe */
|
||||
}
|
||||
sw = sw1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1158,12 +1355,60 @@ static void audio_run_in (AudioState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_run_capture (AudioState *s)
|
||||
{
|
||||
CaptureVoiceOut *cap;
|
||||
|
||||
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
|
||||
int live, rpos, captured;
|
||||
HWVoiceOut *hw = &cap->hw;
|
||||
SWVoiceOut *sw;
|
||||
|
||||
captured = live = audio_pcm_hw_get_live_out (hw);
|
||||
rpos = hw->rpos;
|
||||
while (live) {
|
||||
int left = hw->samples - rpos;
|
||||
int to_capture = audio_MIN (live, left);
|
||||
st_sample_t *src;
|
||||
struct capture_callback *cb;
|
||||
|
||||
src = hw->mix_buf + rpos;
|
||||
hw->clip (cap->buf, src, to_capture);
|
||||
mixeng_clear (src, to_capture);
|
||||
|
||||
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
|
||||
cb->ops.capture (cb->opaque, cap->buf,
|
||||
to_capture << hw->info.shift);
|
||||
}
|
||||
rpos = (rpos + to_capture) % hw->samples;
|
||||
live -= to_capture;
|
||||
}
|
||||
hw->rpos = rpos;
|
||||
|
||||
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
|
||||
if (!sw->active && sw->empty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) {
|
||||
dolog ("captured=%d sw->total_hw_samples_mixed=%d\n",
|
||||
captured, sw->total_hw_samples_mixed);
|
||||
captured = sw->total_hw_samples_mixed;
|
||||
}
|
||||
|
||||
sw->total_hw_samples_mixed -= captured;
|
||||
sw->empty = sw->total_hw_samples_mixed == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_timer (void *opaque)
|
||||
{
|
||||
AudioState *s = opaque;
|
||||
|
||||
audio_run_out (s);
|
||||
audio_run_in (s);
|
||||
audio_run_capture (s);
|
||||
|
||||
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
|
||||
}
|
||||
@@ -1327,8 +1572,19 @@ static void audio_atexit (void)
|
||||
HWVoiceIn *hwi = NULL;
|
||||
|
||||
while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
|
||||
SWVoiceCap *sc;
|
||||
|
||||
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
|
||||
hwo->pcm_ops->fini_out (hwo);
|
||||
|
||||
for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
|
||||
CaptureVoiceOut *cap = sc->cap;
|
||||
struct capture_callback *cb;
|
||||
|
||||
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
|
||||
cb->ops.destroy (cb->opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
|
||||
@@ -1383,6 +1639,7 @@ AudioState *AUD_init (void)
|
||||
|
||||
LIST_INIT (&s->hw_head_out);
|
||||
LIST_INIT (&s->hw_head_in);
|
||||
LIST_INIT (&s->cap_head);
|
||||
atexit (audio_atexit);
|
||||
|
||||
s->ts = qemu_new_timer (vm_clock, audio_timer, s);
|
||||
@@ -1479,3 +1736,136 @@ AudioState *AUD_init (void)
|
||||
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
|
||||
return s;
|
||||
}
|
||||
|
||||
CaptureVoiceOut *AUD_add_capture (
|
||||
AudioState *s,
|
||||
audsettings_t *as,
|
||||
struct audio_capture_ops *ops,
|
||||
void *cb_opaque
|
||||
)
|
||||
{
|
||||
CaptureVoiceOut *cap;
|
||||
struct capture_callback *cb;
|
||||
|
||||
if (!s) {
|
||||
/* XXX suppress */
|
||||
s = &glob_audio_state;
|
||||
}
|
||||
|
||||
if (audio_validate_settings (as)) {
|
||||
dolog ("Invalid settings were passed when trying to add capture\n");
|
||||
audio_print_settings (as);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb));
|
||||
if (!cb) {
|
||||
dolog ("Could not allocate capture callback information, size %zu\n",
|
||||
sizeof (*cb));
|
||||
goto err0;
|
||||
}
|
||||
cb->ops = *ops;
|
||||
cb->opaque = cb_opaque;
|
||||
|
||||
cap = audio_pcm_capture_find_specific (s, as);
|
||||
if (cap) {
|
||||
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
|
||||
return cap;
|
||||
}
|
||||
else {
|
||||
HWVoiceOut *hw;
|
||||
CaptureVoiceOut *cap;
|
||||
|
||||
cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap));
|
||||
if (!cap) {
|
||||
dolog ("Could not allocate capture voice, size %zu\n",
|
||||
sizeof (*cap));
|
||||
goto err1;
|
||||
}
|
||||
|
||||
hw = &cap->hw;
|
||||
LIST_INIT (&hw->sw_head);
|
||||
LIST_INIT (&cap->cb_head);
|
||||
|
||||
/* XXX find a more elegant way */
|
||||
hw->samples = 4096 * 4;
|
||||
hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples,
|
||||
sizeof (st_sample_t));
|
||||
if (!hw->mix_buf) {
|
||||
dolog ("Could not allocate capture mix buffer (%d samples)\n",
|
||||
hw->samples);
|
||||
goto err2;
|
||||
}
|
||||
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
|
||||
cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
|
||||
if (!cap->buf) {
|
||||
dolog ("Could not allocate capture buffer "
|
||||
"(%d samples, each %d bytes)\n",
|
||||
hw->samples, 1 << hw->info.shift);
|
||||
goto err3;
|
||||
}
|
||||
|
||||
hw->clip = mixeng_clip
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.sign]
|
||||
[hw->info.swap_endianness]
|
||||
[hw->info.bits == 16];
|
||||
|
||||
LIST_INSERT_HEAD (&s->cap_head, cap, entries);
|
||||
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
|
||||
|
||||
hw = NULL;
|
||||
while ((hw = audio_pcm_hw_find_any_out (s, hw))) {
|
||||
audio_attach_capture (s, hw);
|
||||
}
|
||||
return cap;
|
||||
|
||||
err3:
|
||||
qemu_free (cap->hw.mix_buf);
|
||||
err2:
|
||||
qemu_free (cap);
|
||||
err1:
|
||||
qemu_free (cb);
|
||||
err0:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
|
||||
{
|
||||
struct capture_callback *cb;
|
||||
|
||||
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
|
||||
if (cb->opaque == cb_opaque) {
|
||||
cb->ops.destroy (cb_opaque);
|
||||
LIST_REMOVE (cb, entries);
|
||||
qemu_free (cb);
|
||||
|
||||
if (!cap->cb_head.lh_first) {
|
||||
SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;
|
||||
|
||||
while (sw) {
|
||||
SWVoiceCap *sc = (SWVoiceCap *) sw;
|
||||
#ifdef DEBUG_CAPTURE
|
||||
dolog ("freeing %s\n", sw->name);
|
||||
#endif
|
||||
|
||||
sw1 = sw->entries.le_next;
|
||||
if (sw->rate) {
|
||||
st_rate_stop (sw->rate);
|
||||
sw->rate = NULL;
|
||||
}
|
||||
LIST_REMOVE (sw, entries);
|
||||
LIST_REMOVE (sc, entries);
|
||||
qemu_free (sc);
|
||||
sw = sw1;
|
||||
}
|
||||
LIST_REMOVE (cap, entries);
|
||||
qemu_free (cap);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef QEMU_AUDIO_H
|
||||
#define QEMU_AUDIO_H
|
||||
|
||||
#include "config.h"
|
||||
#include "sys-queue.h"
|
||||
|
||||
typedef void (*audio_callback_fn_t) (void *opaque, int avail);
|
||||
@@ -35,14 +36,44 @@ typedef enum {
|
||||
AUD_FMT_S16
|
||||
} audfmt_e;
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define AUDIO_HOST_ENDIANNESS 1
|
||||
#else
|
||||
#define AUDIO_HOST_ENDIANNESS 0
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int freq;
|
||||
int nchannels;
|
||||
audfmt_e fmt;
|
||||
int endianness;
|
||||
} audsettings_t;
|
||||
|
||||
typedef enum {
|
||||
AUD_CNOTIFY_ENABLE,
|
||||
AUD_CNOTIFY_DISABLE
|
||||
} audcnotification_e;
|
||||
|
||||
struct audio_capture_ops {
|
||||
void (*notify) (void *opaque, audcnotification_e cmd);
|
||||
void (*capture) (void *opaque, void *buf, int size);
|
||||
void (*destroy) (void *opaque);
|
||||
};
|
||||
|
||||
struct capture_ops {
|
||||
void (*info) (void *opaque);
|
||||
void (*destroy) (void *opaque);
|
||||
};
|
||||
|
||||
typedef struct CaptureState {
|
||||
void *opaque;
|
||||
struct capture_ops ops;
|
||||
LIST_ENTRY (CaptureState) entries;
|
||||
} CaptureState;
|
||||
|
||||
typedef struct AudioState AudioState;
|
||||
typedef struct SWVoiceOut SWVoiceOut;
|
||||
typedef struct CaptureVoiceOut CaptureVoiceOut;
|
||||
typedef struct SWVoiceIn SWVoiceIn;
|
||||
|
||||
typedef struct QEMUSoundCard {
|
||||
@@ -66,6 +97,13 @@ AudioState *AUD_init (void);
|
||||
void AUD_help (void);
|
||||
void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card);
|
||||
void AUD_remove_card (QEMUSoundCard *card);
|
||||
CaptureVoiceOut *AUD_add_capture (
|
||||
AudioState *s,
|
||||
audsettings_t *as,
|
||||
struct audio_capture_ops *ops,
|
||||
void *opaque
|
||||
);
|
||||
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque);
|
||||
|
||||
SWVoiceOut *AUD_open_out (
|
||||
QEMUSoundCard *card,
|
||||
@@ -73,8 +111,7 @@ SWVoiceOut *AUD_open_out (
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn_t callback_fn,
|
||||
audsettings_t *settings,
|
||||
int sw_endian
|
||||
audsettings_t *settings
|
||||
);
|
||||
|
||||
void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
|
||||
@@ -92,8 +129,7 @@ SWVoiceIn *AUD_open_in (
|
||||
const char *name,
|
||||
void *callback_opaque,
|
||||
audio_callback_fn_t callback_fn,
|
||||
audsettings_t *settings,
|
||||
int sw_endian
|
||||
audsettings_t *settings
|
||||
);
|
||||
|
||||
void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
|
||||
@@ -111,7 +147,7 @@ static inline void *advance (void *p, int incr)
|
||||
}
|
||||
|
||||
uint32_t popcount (uint32_t u);
|
||||
inline uint32_t lsbindex (uint32_t u);
|
||||
uint32_t lsbindex (uint32_t u);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define audio_MIN(a, b) ( __extension__ ({ \
|
||||
|
||||
@@ -61,13 +61,14 @@ struct audio_pcm_info {
|
||||
int align;
|
||||
int shift;
|
||||
int bytes_per_second;
|
||||
int swap_endian;
|
||||
int swap_endianness;
|
||||
};
|
||||
|
||||
typedef struct SWVoiceCap SWVoiceCap;
|
||||
|
||||
typedef struct HWVoiceOut {
|
||||
int enabled;
|
||||
int pending_disable;
|
||||
int valid;
|
||||
struct audio_pcm_info info;
|
||||
|
||||
f_sample *clip;
|
||||
@@ -79,6 +80,7 @@ typedef struct HWVoiceOut {
|
||||
|
||||
int samples;
|
||||
LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
|
||||
LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
|
||||
struct audio_pcm_ops *pcm_ops;
|
||||
LIST_ENTRY (HWVoiceOut) entries;
|
||||
} HWVoiceOut;
|
||||
@@ -160,14 +162,34 @@ struct audio_pcm_ops {
|
||||
int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
|
||||
};
|
||||
|
||||
struct capture_callback {
|
||||
struct audio_capture_ops ops;
|
||||
void *opaque;
|
||||
LIST_ENTRY (capture_callback) entries;
|
||||
};
|
||||
|
||||
struct CaptureVoiceOut {
|
||||
HWVoiceOut hw;
|
||||
void *buf;
|
||||
LIST_HEAD (cb_listhead, capture_callback) cb_head;
|
||||
LIST_ENTRY (CaptureVoiceOut) entries;
|
||||
};
|
||||
|
||||
struct SWVoiceCap {
|
||||
SWVoiceOut sw;
|
||||
CaptureVoiceOut *cap;
|
||||
LIST_ENTRY (SWVoiceCap) entries;
|
||||
};
|
||||
|
||||
struct AudioState {
|
||||
struct audio_driver *drv;
|
||||
void *drv_opaque;
|
||||
|
||||
QEMUTimer *ts;
|
||||
LIST_HEAD (card_head, QEMUSoundCard) card_head;
|
||||
LIST_HEAD (card_listhead, QEMUSoundCard) card_head;
|
||||
LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
|
||||
LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
|
||||
LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head;
|
||||
int nb_hw_voices_out;
|
||||
int nb_hw_voices_in;
|
||||
};
|
||||
@@ -182,8 +204,7 @@ extern struct audio_driver coreaudio_audio_driver;
|
||||
extern struct audio_driver dsound_audio_driver;
|
||||
extern volume_t nominal_volume;
|
||||
|
||||
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as,
|
||||
int swap_endian);
|
||||
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as);
|
||||
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
|
||||
|
||||
int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
|
||||
@@ -204,15 +225,6 @@ static inline int audio_ring_dist (int dst, int src, int len)
|
||||
return (dst >= src) ? (dst - src) : (len - src + dst);
|
||||
}
|
||||
|
||||
static inline int audio_need_to_swap_endian (int endianness)
|
||||
{
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
return endianness != 1;
|
||||
#else
|
||||
return endianness != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined __GNUC__
|
||||
#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2)))
|
||||
#define INIT_FIELD(f) . f
|
||||
|
||||
@@ -140,13 +140,12 @@ static int glue (audio_pcm_sw_init_, TYPE) (
|
||||
SW *sw,
|
||||
HW *hw,
|
||||
const char *name,
|
||||
audsettings_t *as,
|
||||
int endian
|
||||
audsettings_t *as
|
||||
)
|
||||
{
|
||||
int err;
|
||||
|
||||
audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian));
|
||||
audio_pcm_init_info (&sw->info, as);
|
||||
sw->hw = hw;
|
||||
sw->active = 0;
|
||||
#ifdef DAC
|
||||
@@ -164,7 +163,7 @@ static int glue (audio_pcm_sw_init_, TYPE) (
|
||||
#endif
|
||||
[sw->info.nchannels == 2]
|
||||
[sw->info.sign]
|
||||
[sw->info.swap_endian]
|
||||
[sw->info.swap_endianness]
|
||||
[sw->info.bits == 16];
|
||||
|
||||
sw->name = qemu_strdup (name);
|
||||
@@ -200,6 +199,9 @@ static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp)
|
||||
HW *hw = *hwp;
|
||||
|
||||
if (!hw->sw_head.lh_first) {
|
||||
#ifdef DAC
|
||||
audio_detach_capture (hw);
|
||||
#endif
|
||||
LIST_REMOVE (hw, entries);
|
||||
glue (s->nb_hw_voices_, TYPE) += 1;
|
||||
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
|
||||
@@ -266,7 +268,9 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
|
||||
|
||||
hw->pcm_ops = drv->pcm_ops;
|
||||
LIST_INIT (&hw->sw_head);
|
||||
|
||||
#ifdef DAC
|
||||
LIST_INIT (&hw->cap_head);
|
||||
#endif
|
||||
if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
|
||||
goto err0;
|
||||
}
|
||||
@@ -283,7 +287,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
|
||||
#endif
|
||||
[hw->info.nchannels == 2]
|
||||
[hw->info.sign]
|
||||
[hw->info.swap_endian]
|
||||
[hw->info.swap_endianness]
|
||||
[hw->info.bits == 16];
|
||||
|
||||
if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
|
||||
@@ -292,6 +296,9 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
|
||||
|
||||
LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
|
||||
glue (s->nb_hw_voices_, TYPE) -= 1;
|
||||
#ifdef DAC
|
||||
audio_attach_capture (s, hw);
|
||||
#endif
|
||||
return hw;
|
||||
|
||||
err1:
|
||||
@@ -328,8 +335,7 @@ static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as)
|
||||
static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
|
||||
AudioState *s,
|
||||
const char *sw_name,
|
||||
audsettings_t *as,
|
||||
int sw_endian
|
||||
audsettings_t *as
|
||||
)
|
||||
{
|
||||
SW *sw;
|
||||
@@ -357,7 +363,7 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
|
||||
|
||||
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
|
||||
|
||||
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) {
|
||||
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
|
||||
goto err3;
|
||||
}
|
||||
|
||||
@@ -399,8 +405,7 @@ SW *glue (AUD_open_, TYPE) (
|
||||
const char *name,
|
||||
void *callback_opaque ,
|
||||
audio_callback_fn_t callback_fn,
|
||||
audsettings_t *as,
|
||||
int sw_endian
|
||||
audsettings_t *as
|
||||
)
|
||||
{
|
||||
AudioState *s;
|
||||
@@ -421,7 +426,7 @@ SW *glue (AUD_open_, TYPE) (
|
||||
|
||||
s = card->audio;
|
||||
|
||||
if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) {
|
||||
if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
|
||||
audio_print_settings (as);
|
||||
goto fail;
|
||||
}
|
||||
@@ -473,12 +478,12 @@ SW *glue (AUD_open_, TYPE) (
|
||||
}
|
||||
|
||||
glue (audio_pcm_sw_fini_, TYPE) (sw);
|
||||
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) {
|
||||
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian);
|
||||
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as);
|
||||
if (!sw) {
|
||||
dolog ("Failed to create voice `%s'\n", name);
|
||||
return NULL;
|
||||
|
||||
@@ -275,8 +275,6 @@ static OSStatus audioDeviceIOProc(
|
||||
#endif
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
mixeng_clear (src, frameCount);
|
||||
rpos = (rpos + frameCount) % hw->samples;
|
||||
core->decr += frameCount;
|
||||
core->rpos = rpos;
|
||||
@@ -297,7 +295,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
UInt32 propertySize;
|
||||
int err;
|
||||
int bits = 8;
|
||||
int endianess = 0;
|
||||
const char *typ = "playback";
|
||||
AudioValueRange frameRange;
|
||||
|
||||
@@ -310,16 +307,9 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
|
||||
if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
|
||||
bits = 16;
|
||||
endianess = 1;
|
||||
}
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
as,
|
||||
/* Following is irrelevant actually since we do not use
|
||||
mixengs clipping routines */
|
||||
audio_need_to_swap_endian (endianess)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
|
||||
/* open default output device */
|
||||
propertySize = sizeof(core->outputDeviceID);
|
||||
|
||||
@@ -70,7 +70,13 @@ static int glue (dsound_lock_, TYPE) (
|
||||
int i;
|
||||
LPVOID p1 = NULL, p2 = NULL;
|
||||
DWORD blen1 = 0, blen2 = 0;
|
||||
DWORD flag;
|
||||
|
||||
#ifdef DSBTYPE_IN
|
||||
flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
|
||||
#else
|
||||
flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
|
||||
#endif
|
||||
for (i = 0; i < conf.lock_retries; ++i) {
|
||||
hr = glue (IFACE, _Lock) (
|
||||
buf,
|
||||
@@ -80,13 +86,7 @@ static int glue (dsound_lock_, TYPE) (
|
||||
&blen1,
|
||||
&p2,
|
||||
&blen2,
|
||||
(entire
|
||||
#ifdef DSBTYPE_IN
|
||||
? DSCBLOCK_ENTIREBUFFER
|
||||
#else
|
||||
? DSBLOCK_ENTIREBUFFER
|
||||
#endif
|
||||
: 0)
|
||||
flag
|
||||
);
|
||||
|
||||
if (FAILED (hr)) {
|
||||
@@ -250,8 +250,8 @@ static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
}
|
||||
|
||||
ds->first_time = 1;
|
||||
|
||||
audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0));
|
||||
obt_as.endianness = 0;
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
|
||||
if (bc.dwBufferBytes & hw->info.align) {
|
||||
dolog (
|
||||
|
||||
@@ -453,13 +453,11 @@ static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
|
||||
|
||||
if (src_len1) {
|
||||
hw->clip (dst, src1, src_len1);
|
||||
mixeng_clear (src1, src_len1);
|
||||
}
|
||||
|
||||
if (src_len2) {
|
||||
dst = advance (dst, src_len1 << hw->info.shift);
|
||||
hw->clip (dst, src2, src_len2);
|
||||
mixeng_clear (src2, src_len2);
|
||||
}
|
||||
|
||||
hw->rpos = pos % hw->samples;
|
||||
@@ -987,6 +985,12 @@ static void *dsound_audio_init (void)
|
||||
hr = IDirectSound_Initialize (s->dsound, NULL);
|
||||
if (FAILED (hr)) {
|
||||
dsound_logerr (hr, "Could not initialize DirectSound\n");
|
||||
|
||||
hr = IDirectSound_Release (s->dsound);
|
||||
if (FAILED (hr)) {
|
||||
dsound_logerr (hr, "Could not release DirectSound\n");
|
||||
}
|
||||
s->dsound = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,13 +153,11 @@ static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
|
||||
|
||||
if (src_len1) {
|
||||
hw->clip (dst, src1, src_len1);
|
||||
mixeng_clear (src1, src_len1);
|
||||
}
|
||||
|
||||
if (src_len2) {
|
||||
dst = advance (dst, src_len1 << hw->info.shift);
|
||||
hw->clip (dst, src2, src_len2);
|
||||
mixeng_clear (src2, src_len2);
|
||||
}
|
||||
|
||||
hw->rpos = pos % hw->samples;
|
||||
@@ -360,6 +358,7 @@ static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
{
|
||||
int bits16, mode, channel;
|
||||
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
|
||||
audsettings_t obt_as = *as;
|
||||
|
||||
mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
|
||||
fmd->fmod_sample = FSOUND_Sample_Alloc (
|
||||
@@ -386,7 +385,8 @@ static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
fmd->channel = channel;
|
||||
|
||||
/* FMOD always operates on little endian frames? */
|
||||
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
|
||||
obt_as.endianness = 0;
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
bits16 = (mode & FSOUND_16BITS) != 0;
|
||||
hw->samples = conf.nb_samples;
|
||||
return 0;
|
||||
@@ -420,6 +420,7 @@ static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
|
||||
{
|
||||
int bits16, mode;
|
||||
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
|
||||
audsettings_t obt_as = *as;
|
||||
|
||||
if (conf.broken_adc) {
|
||||
return -1;
|
||||
@@ -442,7 +443,8 @@ static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
|
||||
}
|
||||
|
||||
/* FMOD always operates on little endian frames? */
|
||||
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
|
||||
obt_as.endianness = 0;
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
bits16 = (mode & FSOUND_16BITS) != 0;
|
||||
hw->samples = conf.nb_samples;
|
||||
return 0;
|
||||
|
||||
+21
-19
@@ -40,22 +40,21 @@ static int no_run_out (HWVoiceOut *hw)
|
||||
{
|
||||
NoVoiceOut *no = (NoVoiceOut *) hw;
|
||||
int live, decr, samples;
|
||||
int64_t now = qemu_get_clock (vm_clock);
|
||||
int64_t ticks = now - no->old_ticks;
|
||||
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
|
||||
|
||||
if (bytes > INT_MAX) {
|
||||
samples = INT_MAX >> hw->info.shift;
|
||||
}
|
||||
else {
|
||||
samples = bytes >> hw->info.shift;
|
||||
}
|
||||
int64_t now;
|
||||
int64_t ticks;
|
||||
int64_t bytes;
|
||||
|
||||
live = audio_pcm_hw_get_live_out (&no->hw);
|
||||
if (!live) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
now = qemu_get_clock (vm_clock);
|
||||
ticks = now - no->old_ticks;
|
||||
bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
|
||||
bytes = audio_MIN (bytes, INT_MAX);
|
||||
samples = bytes >> hw->info.shift;
|
||||
|
||||
no->old_ticks = now;
|
||||
decr = audio_MIN (live, samples);
|
||||
hw->rpos = (hw->rpos + decr) % hw->samples;
|
||||
@@ -69,7 +68,7 @@ static int no_write (SWVoiceOut *sw, void *buf, int len)
|
||||
|
||||
static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
{
|
||||
audio_pcm_init_info (&hw->info, as, 0);
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
hw->samples = 1024;
|
||||
return 0;
|
||||
}
|
||||
@@ -88,7 +87,7 @@ static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
|
||||
|
||||
static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
|
||||
{
|
||||
audio_pcm_init_info (&hw->info, as, 0);
|
||||
audio_pcm_init_info (&hw->info, as);
|
||||
hw->samples = 1024;
|
||||
return 0;
|
||||
}
|
||||
@@ -101,17 +100,20 @@ static void no_fini_in (HWVoiceIn *hw)
|
||||
static int no_run_in (HWVoiceIn *hw)
|
||||
{
|
||||
NoVoiceIn *no = (NoVoiceIn *) hw;
|
||||
int64_t now = qemu_get_clock (vm_clock);
|
||||
int64_t ticks = now - no->old_ticks;
|
||||
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
|
||||
int live = audio_pcm_hw_get_live_in (hw);
|
||||
int dead = hw->samples - live;
|
||||
int samples;
|
||||
int samples = 0;
|
||||
|
||||
bytes = audio_MIN (bytes, INT_MAX);
|
||||
samples = bytes >> hw->info.shift;
|
||||
samples = audio_MIN (samples, dead);
|
||||
if (dead) {
|
||||
int64_t now = qemu_get_clock (vm_clock);
|
||||
int64_t ticks = now - no->old_ticks;
|
||||
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
|
||||
|
||||
no->old_ticks = now;
|
||||
bytes = audio_MIN (bytes, INT_MAX);
|
||||
samples = bytes >> hw->info.shift;
|
||||
samples = audio_MIN (samples, dead);
|
||||
}
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,14 @@ static struct {
|
||||
int fragsize;
|
||||
const char *devpath_out;
|
||||
const char *devpath_in;
|
||||
int debug;
|
||||
} conf = {
|
||||
.try_mmap = 0,
|
||||
.nfrags = 4,
|
||||
.fragsize = 4096,
|
||||
.devpath_out = "/dev/dsp",
|
||||
.devpath_in = "/dev/dsp"
|
||||
.devpath_in = "/dev/dsp",
|
||||
.debug = 0
|
||||
};
|
||||
|
||||
struct oss_params {
|
||||
@@ -324,9 +326,20 @@ static int oss_run_out (HWVoiceOut *hw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
|
||||
ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
|
||||
abinfo.bytes, bufsize);
|
||||
if (abinfo.bytes > bufsize) {
|
||||
if (conf.debug) {
|
||||
dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
|
||||
"please report your OS/audio hw to malc@pulsesoft.com\n",
|
||||
abinfo.bytes, bufsize);
|
||||
}
|
||||
abinfo.bytes = bufsize;
|
||||
}
|
||||
|
||||
if (abinfo.bytes < 0) {
|
||||
if (conf.debug) {
|
||||
dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
|
||||
abinfo.bytes, bufsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -369,15 +382,12 @@ static int oss_run_out (HWVoiceOut *hw)
|
||||
"alignment %d\n",
|
||||
wbytes, written, hw->info.align + 1);
|
||||
}
|
||||
mixeng_clear (src, wsamples);
|
||||
decr -= wsamples;
|
||||
rpos = (rpos + wsamples) % hw->samples;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mixeng_clear (src, convert_samples);
|
||||
|
||||
rpos = (rpos + convert_samples) % hw->samples;
|
||||
samples -= convert_samples;
|
||||
}
|
||||
@@ -443,12 +453,9 @@ static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.nchannels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianness;
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
&obt_as,
|
||||
audio_need_to_swap_endian (endianness)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
oss->nfrags = obt.nfrags;
|
||||
oss->fragsize = obt.fragsize;
|
||||
|
||||
@@ -587,12 +594,9 @@ static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.nchannels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianness;
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
&obt_as,
|
||||
audio_need_to_swap_endian (endianness)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
oss->nfrags = obt.nfrags;
|
||||
oss->fragsize = obt.fragsize;
|
||||
|
||||
@@ -730,6 +734,8 @@ static struct audio_option oss_options[] = {
|
||||
"Path to DAC device", NULL, 0},
|
||||
{"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
|
||||
"Path to ADC device", NULL, 0},
|
||||
{"DEBUG", AUD_OPT_BOOL, &conf.debug,
|
||||
"Turn on some debugging messages", NULL, 0},
|
||||
{NULL, 0, NULL, NULL, NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ void NAME (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
|
||||
if (rate->opos_inc == (1ULL + UINT_MAX)) {
|
||||
int i, n = *isamp > *osamp ? *osamp : *isamp;
|
||||
for (i = 0; i < n; i++) {
|
||||
OP (obuf[i].l, ibuf[i].r);
|
||||
OP (obuf[i].l, ibuf[i].l);
|
||||
OP (obuf[i].r, ibuf[i].r);
|
||||
}
|
||||
*isamp = n;
|
||||
|
||||
@@ -240,7 +240,6 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
|
||||
|
||||
/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
|
||||
hw->clip (buf, src, chunk);
|
||||
mixeng_clear (src, chunk);
|
||||
sdl->rpos = (sdl->rpos + chunk) % hw->samples;
|
||||
to_mix -= chunk;
|
||||
buf += chunk << hw->info.shift;
|
||||
@@ -336,12 +335,9 @@ static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.channels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianess;
|
||||
|
||||
audio_pcm_init_info (
|
||||
&hw->info,
|
||||
&obt_as,
|
||||
audio_need_to_swap_endian (endianess)
|
||||
);
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = obt.samples;
|
||||
|
||||
s->initialized = 1;
|
||||
|
||||
@@ -81,7 +81,6 @@ static int wav_run_out (HWVoiceOut *hw)
|
||||
|
||||
hw->clip (dst, src, convert_samples);
|
||||
qemu_put_buffer (wav->f, dst, convert_samples << hw->info.shift);
|
||||
mixeng_clear (src, convert_samples);
|
||||
|
||||
rpos = (rpos + convert_samples) % hw->samples;
|
||||
samples -= convert_samples;
|
||||
@@ -136,7 +135,8 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
|
||||
|
||||
hdr[34] = bits16 ? 0x10 : 0x08;
|
||||
|
||||
audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0));
|
||||
wav_as.endianness = 0;
|
||||
audio_pcm_init_info (&hw->info, &wav_as);
|
||||
|
||||
hw->samples = 1024;
|
||||
wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
#include "vl.h"
|
||||
|
||||
typedef struct {
|
||||
QEMUFile *f;
|
||||
int bytes;
|
||||
char *path;
|
||||
int freq;
|
||||
int bits;
|
||||
int nchannels;
|
||||
CaptureVoiceOut *cap;
|
||||
} WAVState;
|
||||
|
||||
/* VICE code: Store number as little endian. */
|
||||
static void le_store (uint8_t *buf, uint32_t val, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = (uint8_t) (val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void wav_notify (void *opaque, audcnotification_e cmd)
|
||||
{
|
||||
(void) opaque;
|
||||
(void) cmd;
|
||||
}
|
||||
|
||||
static void wav_destroy (void *opaque)
|
||||
{
|
||||
WAVState *wav = opaque;
|
||||
uint8_t rlen[4];
|
||||
uint8_t dlen[4];
|
||||
uint32_t datalen = wav->bytes;
|
||||
uint32_t rifflen = datalen + 36;
|
||||
|
||||
if (!wav->f) {
|
||||
return;
|
||||
}
|
||||
|
||||
le_store (rlen, rifflen, 4);
|
||||
le_store (dlen, datalen, 4);
|
||||
|
||||
qemu_fseek (wav->f, 4, SEEK_SET);
|
||||
qemu_put_buffer (wav->f, rlen, 4);
|
||||
|
||||
qemu_fseek (wav->f, 32, SEEK_CUR);
|
||||
qemu_put_buffer (wav->f, dlen, 4);
|
||||
fclose (wav->f);
|
||||
if (wav->path) {
|
||||
qemu_free (wav->path);
|
||||
}
|
||||
}
|
||||
|
||||
static void wav_capture (void *opaque, void *buf, int size)
|
||||
{
|
||||
WAVState *wav = opaque;
|
||||
|
||||
qemu_put_buffer (wav->f, buf, size);
|
||||
wav->bytes += size;
|
||||
}
|
||||
|
||||
static void wav_capture_destroy (void *opaque)
|
||||
{
|
||||
WAVState *wav = opaque;
|
||||
|
||||
AUD_del_capture (wav->cap, wav);
|
||||
}
|
||||
|
||||
static void wav_capture_info (void *opaque)
|
||||
{
|
||||
WAVState *wav = opaque;
|
||||
char *path = wav->path;
|
||||
|
||||
term_printf ("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
|
||||
wav->freq, wav->bits, wav->nchannels,
|
||||
path ? path : "<not available>", wav->bytes);
|
||||
}
|
||||
|
||||
static struct capture_ops wav_capture_ops = {
|
||||
.destroy = wav_capture_destroy,
|
||||
.info = wav_capture_info
|
||||
};
|
||||
|
||||
int wav_start_capture (CaptureState *s, const char *path, int freq,
|
||||
int bits, int nchannels)
|
||||
{
|
||||
WAVState *wav;
|
||||
uint8_t hdr[] = {
|
||||
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
|
||||
0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
|
||||
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
audsettings_t as;
|
||||
struct audio_capture_ops ops;
|
||||
int stereo, bits16, shift;
|
||||
CaptureVoiceOut *cap;
|
||||
|
||||
if (bits != 8 && bits != 16) {
|
||||
term_printf ("incorrect bit count %d, must be 8 or 16\n", bits);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nchannels != 1 && nchannels != 2) {
|
||||
term_printf ("incorrect channel count %d, must be 1 or 2\n",
|
||||
nchannels);
|
||||
return -1;
|
||||
}
|
||||
|
||||
stereo = nchannels == 2;
|
||||
bits16 = bits == 16;
|
||||
|
||||
as.freq = freq;
|
||||
as.nchannels = 1 << stereo;
|
||||
as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
|
||||
as.endianness = 0;
|
||||
|
||||
ops.notify = wav_notify;
|
||||
ops.capture = wav_capture;
|
||||
ops.destroy = wav_destroy;
|
||||
|
||||
wav = qemu_mallocz (sizeof (*wav));
|
||||
if (!wav) {
|
||||
term_printf ("Could not allocate memory for wav capture (%zu bytes)",
|
||||
sizeof (*wav));
|
||||
return -1;
|
||||
}
|
||||
|
||||
shift = bits16 + stereo;
|
||||
hdr[34] = bits16 ? 0x10 : 0x08;
|
||||
|
||||
le_store (hdr + 22, as.nchannels, 2);
|
||||
le_store (hdr + 24, freq, 4);
|
||||
le_store (hdr + 28, freq << shift, 4);
|
||||
le_store (hdr + 32, 1 << shift, 2);
|
||||
|
||||
wav->f = fopen (path, "wb");
|
||||
if (!wav->f) {
|
||||
term_printf ("Failed to open wave file `%s'\nReason: %s\n",
|
||||
path, strerror (errno));
|
||||
qemu_free (wav);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wav->path = qemu_strdup (path);
|
||||
wav->bits = bits;
|
||||
wav->nchannels = nchannels;
|
||||
wav->freq = freq;
|
||||
|
||||
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
|
||||
|
||||
cap = AUD_add_capture (NULL, &as, &ops, wav);
|
||||
if (!cap) {
|
||||
term_printf ("Failed to add audio capture\n");
|
||||
qemu_free (wav);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wav->cap = cap;
|
||||
s->opaque = wav;
|
||||
s->ops = wav_capture_ops;
|
||||
return 0;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename)
|
||||
int fd, i;
|
||||
struct bochs_header bochs;
|
||||
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (fd < 0) {
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
if (fd < 0)
|
||||
|
||||
@@ -55,7 +55,7 @@ static int cloop_open(BlockDriverState *bs, const char *filename)
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
uint32_t offsets_size,max_compressed_block_size=1,i;
|
||||
|
||||
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (s->fd < 0)
|
||||
return -1;
|
||||
bs->read_only = 1;
|
||||
|
||||
@@ -69,7 +69,7 @@ static int cow_open(BlockDriverState *bs, const char *filename)
|
||||
struct cow_header_v2 cow_header;
|
||||
int64_t size;
|
||||
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (fd < 0) {
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
if (fd < 0)
|
||||
@@ -250,6 +250,12 @@ static int cow_create(const char *filename, int64_t image_sectors,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cow_flush(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCowState *s = bs->opaque;
|
||||
fsync(s->fd);
|
||||
}
|
||||
|
||||
BlockDriver bdrv_cow = {
|
||||
"cow",
|
||||
sizeof(BDRVCowState),
|
||||
@@ -259,6 +265,7 @@ BlockDriver bdrv_cow = {
|
||||
cow_write,
|
||||
cow_close,
|
||||
cow_create,
|
||||
cow_flush,
|
||||
cow_is_allocated,
|
||||
};
|
||||
#endif
|
||||
@@ -95,7 +95,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename)
|
||||
int fd, len, i, shift;
|
||||
QCowHeader header;
|
||||
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (fd < 0) {
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
if (fd < 0)
|
||||
@@ -693,6 +693,12 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcow_flush(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
fsync(s->fd);
|
||||
}
|
||||
|
||||
BlockDriver bdrv_qcow = {
|
||||
"qcow",
|
||||
sizeof(BDRVQcowState),
|
||||
@@ -702,6 +708,7 @@ BlockDriver bdrv_qcow = {
|
||||
qcow_write,
|
||||
qcow_close,
|
||||
qcow_create,
|
||||
qcow_flush,
|
||||
qcow_is_allocated,
|
||||
qcow_set_key,
|
||||
qcow_make_empty
|
||||
|
||||
@@ -96,7 +96,7 @@ static int vmdk_open(BlockDriverState *bs, const char *filename)
|
||||
uint32_t magic;
|
||||
int l1_size;
|
||||
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (fd < 0) {
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
if (fd < 0)
|
||||
@@ -426,6 +426,12 @@ static void vmdk_close(BlockDriverState *bs)
|
||||
close(s->fd);
|
||||
}
|
||||
|
||||
static void vmdk_flush(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
fsync(s->fd);
|
||||
}
|
||||
|
||||
BlockDriver bdrv_vmdk = {
|
||||
"vmdk",
|
||||
sizeof(BDRVVmdkState),
|
||||
@@ -435,5 +441,6 @@ BlockDriver bdrv_vmdk = {
|
||||
vmdk_write,
|
||||
vmdk_close,
|
||||
vmdk_create,
|
||||
vmdk_flush,
|
||||
vmdk_is_allocated,
|
||||
};
|
||||
@@ -163,7 +163,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
|
||||
bitmap_offset = 512 * s->pagetable[pagetable_index];
|
||||
block_offset = bitmap_offset + 512 + (512 * pageentry_index);
|
||||
|
||||
// printf("sector: %llx, index: %x, offset: %x, bioff: %llx, bloff: %llx\n",
|
||||
// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
|
||||
// sector_num, pagetable_index, pageentry_index,
|
||||
// bitmap_offset, block_offset);
|
||||
|
||||
|
||||
@@ -2772,6 +2772,7 @@ BlockDriver bdrv_vvfat = {
|
||||
vvfat_read,
|
||||
vvfat_write,
|
||||
vvfat_close,
|
||||
NULL, /* ??? Not sure if we can do any meaningful flushing. */
|
||||
NULL,
|
||||
vvfat_is_allocated
|
||||
};
|
||||
|
||||
+63
-1
@@ -615,6 +615,14 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
|
||||
return bs->device_name;
|
||||
}
|
||||
|
||||
void bdrv_flush(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->drv->bdrv_flush)
|
||||
bs->drv->bdrv_flush(bs);
|
||||
if (bs->backing_hd)
|
||||
bdrv_flush(bs->backing_hd);
|
||||
}
|
||||
|
||||
void bdrv_info(void)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
@@ -677,7 +685,7 @@ static int raw_open(BlockDriverState *bs, const char *filename)
|
||||
int rv;
|
||||
#endif
|
||||
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
|
||||
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE | O_SYNC);
|
||||
if (fd < 0) {
|
||||
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
|
||||
if (fd < 0)
|
||||
@@ -750,9 +758,55 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
|
||||
static void raw_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
bs->total_sectors = 0;
|
||||
close(s->fd);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
int qemu_ftruncate64(int fd, int64_t length)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
LONG high;
|
||||
HANDLE h;
|
||||
BOOL res;
|
||||
|
||||
if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
|
||||
return -1;
|
||||
|
||||
h = (HANDLE)_get_osfhandle(fd);
|
||||
|
||||
/* get current position, ftruncate do not change position */
|
||||
li.HighPart = 0;
|
||||
li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
|
||||
if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
|
||||
return -1;
|
||||
|
||||
high = length >> 32;
|
||||
if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
|
||||
return -1;
|
||||
res = SetEndOfFile(h);
|
||||
|
||||
/* back to old position */
|
||||
SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
|
||||
return res ? 0 : -1;
|
||||
}
|
||||
|
||||
static int set_sparse(int fd)
|
||||
{
|
||||
DWORD returned;
|
||||
return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
|
||||
NULL, 0, NULL, 0, &returned, NULL);
|
||||
}
|
||||
#else
|
||||
static inline int set_sparse(int fd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int raw_create(const char *filename, int64_t total_size,
|
||||
const char *backing_file, int flags)
|
||||
{
|
||||
@@ -765,11 +819,18 @@ static int raw_create(const char *filename, int64_t total_size,
|
||||
0644);
|
||||
if (fd < 0)
|
||||
return -EIO;
|
||||
set_sparse(fd);
|
||||
ftruncate(fd, total_size * 512);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void raw_flush(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
fsync(s->fd);
|
||||
}
|
||||
|
||||
BlockDriver bdrv_raw = {
|
||||
"raw",
|
||||
sizeof(BDRVRawState),
|
||||
@@ -779,6 +840,7 @@ BlockDriver bdrv_raw = {
|
||||
raw_write,
|
||||
raw_close,
|
||||
raw_create,
|
||||
raw_flush,
|
||||
};
|
||||
|
||||
void bdrv_init(void)
|
||||
|
||||
@@ -36,6 +36,7 @@ struct BlockDriver {
|
||||
void (*bdrv_close)(BlockDriverState *bs);
|
||||
int (*bdrv_create)(const char *filename, int64_t total_sectors,
|
||||
const char *backing_file, int flags);
|
||||
void (*bdrv_flush)(BlockDriverState *bs);
|
||||
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
|
||||
int nb_sectors, int *pnum);
|
||||
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
|
||||
|
||||
+36
-20
@@ -439,23 +439,40 @@ static void cocoa_refresh(DisplayState *ds)
|
||||
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
|
||||
/* handle monitor key events */
|
||||
} else {
|
||||
int keysym = 0;
|
||||
|
||||
switch([event keyCode]) {
|
||||
case 123:
|
||||
kbd_put_keysym(QEMU_KEY_LEFT);
|
||||
break;
|
||||
case 124:
|
||||
kbd_put_keysym(QEMU_KEY_RIGHT);
|
||||
break;
|
||||
case 125:
|
||||
kbd_put_keysym(QEMU_KEY_DOWN);
|
||||
break;
|
||||
case 126:
|
||||
kbd_put_keysym(QEMU_KEY_UP);
|
||||
break;
|
||||
default:
|
||||
kbd_put_keysym([[event characters] characterAtIndex:0]);
|
||||
break;
|
||||
case 115:
|
||||
keysym = QEMU_KEY_HOME;
|
||||
break;
|
||||
case 117:
|
||||
keysym = QEMU_KEY_DELETE;
|
||||
break;
|
||||
case 119:
|
||||
keysym = QEMU_KEY_END;
|
||||
break;
|
||||
case 123:
|
||||
keysym = QEMU_KEY_LEFT;
|
||||
break;
|
||||
case 124:
|
||||
keysym = QEMU_KEY_RIGHT;
|
||||
break;
|
||||
case 125:
|
||||
keysym = QEMU_KEY_DOWN;
|
||||
break;
|
||||
case 126:
|
||||
keysym = QEMU_KEY_UP;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
NSString *ks = [event characters];
|
||||
|
||||
if ([ks length] > 0)
|
||||
keysym = [ks characterAtIndex:0];
|
||||
}
|
||||
}
|
||||
if (keysym)
|
||||
kbd_put_keysym(keysym);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -867,10 +884,9 @@ static void setupWindowMenu(void)
|
||||
/* Finally give up our references to the objects */
|
||||
[windowMenu release];
|
||||
[windowMenuItem release];
|
||||
|
||||
}
|
||||
|
||||
static void CustomApplicationMain (argc, argv)
|
||||
static void CustomApplicationMain(void)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
QemuCocoaGUIController *gui_controller;
|
||||
@@ -904,8 +920,8 @@ int main(int argc, char **argv)
|
||||
{
|
||||
gArgc = argc;
|
||||
gArgv = argv;
|
||||
|
||||
CustomApplicationMain (argc, argv);
|
||||
|
||||
|
||||
CustomApplicationMain();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+38
-17
@@ -96,6 +96,8 @@ check_gcc="no"
|
||||
softmmu="yes"
|
||||
user="no"
|
||||
build_docs="no"
|
||||
build_acpi_tables="no"
|
||||
uname_release=""
|
||||
|
||||
# OS specific
|
||||
targetos=`uname -s`
|
||||
@@ -212,7 +214,7 @@ for opt do
|
||||
;;
|
||||
--fmod-inc=*) fmod_inc="$optarg"
|
||||
;;
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
|
||||
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
|
||||
;;
|
||||
--disable-slirp) slirp="no"
|
||||
;;
|
||||
@@ -226,8 +228,6 @@ for opt do
|
||||
;;
|
||||
--enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
|
||||
;;
|
||||
--disable-gfx-check) check_gfx="no"
|
||||
;;
|
||||
--disable-gcc-check) check_gcc="no"
|
||||
;;
|
||||
--disable-system) softmmu="no"
|
||||
@@ -238,6 +238,10 @@ for opt do
|
||||
;;
|
||||
--enable-user) user="yes"
|
||||
;;
|
||||
--enable-uname-release=*) uname_release="$optarg"
|
||||
;;
|
||||
--enable-iasl) build_acpi_tables="yes"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -285,6 +289,8 @@ echo " --enable-user enable all linux usermode emulation targets"
|
||||
echo " --disable-user disable all linux usermode emulation targets"
|
||||
echo " --fmod-lib path to FMOD library"
|
||||
echo " --fmod-inc path to FMOD includes"
|
||||
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
|
||||
echo " --enable-iasl compilation of ACPI tables with the IASL compiler"
|
||||
echo ""
|
||||
echo "NOTE: The object files are build at the place where configure is launched"
|
||||
exit 1
|
||||
@@ -294,15 +300,21 @@ cc="${cross_prefix}${cc}"
|
||||
ar="${cross_prefix}${ar}"
|
||||
strip="${cross_prefix}${strip}"
|
||||
|
||||
if [ ! -x "`which $cc`" ] ; then
|
||||
echo "Compiler $cc could not be found"
|
||||
exit
|
||||
# check that the C compiler works.
|
||||
cat > $TMPC <<EOF
|
||||
int main(void) {}
|
||||
EOF
|
||||
|
||||
if $cc -c -o $TMPO $TMPC 2>/dev/null ; then
|
||||
: C compiler works ok
|
||||
else
|
||||
echo "ERROR: \"$cc\" either does not exist or does not work"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test "$mingw32" = "yes" ; then
|
||||
linux="no"
|
||||
EXESUF=".exe"
|
||||
gdbstub="no"
|
||||
oss="no"
|
||||
if [ "$cpu" = "i386" ] ; then
|
||||
kqemu="yes"
|
||||
@@ -553,6 +565,8 @@ fi
|
||||
echo "FMOD support $fmod $fmod_support"
|
||||
echo "kqemu support $kqemu"
|
||||
echo "Documentation $build_docs"
|
||||
[ ! -z "$uname_release" ] && \
|
||||
echo "uname -r $uname_release"
|
||||
|
||||
if test $sdl_too_old = "yes"; then
|
||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
|
||||
@@ -705,6 +719,9 @@ echo "TARGET_DIRS=$target_list" >> $config_mak
|
||||
if [ "$build_docs" = "yes" ] ; then
|
||||
echo "BUILD_DOCS=yes" >> $config_mak
|
||||
fi
|
||||
if [ "$build_acpi_tables" = "yes" ] ; then
|
||||
echo "BUILD_ACPI_TABLES=yes" >> $config_mak
|
||||
fi
|
||||
|
||||
# XXX: suppress that
|
||||
if [ "$bsd" = "yes" ] ; then
|
||||
@@ -713,6 +730,8 @@ if [ "$bsd" = "yes" ] ; then
|
||||
echo "#define _BSD 1" >> $config_h
|
||||
fi
|
||||
|
||||
echo "#define CONFIG_UNAME_RELEASE \"$uname_release\"" >> $config_h
|
||||
|
||||
for target in $target_list; do
|
||||
target_dir="$target"
|
||||
config_mak=$target_dir/config.mak
|
||||
@@ -725,6 +744,7 @@ target_bigendian="no"
|
||||
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
|
||||
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
|
||||
[ "$target_cpu" = "mips" ] && target_bigendian=yes
|
||||
[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
|
||||
target_softmmu="no"
|
||||
if expr $target : '.*-softmmu' > /dev/null ; then
|
||||
target_softmmu="yes"
|
||||
@@ -736,14 +756,6 @@ if expr $target : '.*-user' > /dev/null ; then
|
||||
target_user_only="yes"
|
||||
fi
|
||||
|
||||
if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
|
||||
-a "$sdl" = "no" -a "$cocoa" = "no" ; then
|
||||
echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
|
||||
echo "To build QEMU without graphical output configure with --disable-gfx-check"
|
||||
echo "Note that this will disable all output from the virtual graphics card."
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
|
||||
|
||||
mkdir -p $target_dir
|
||||
@@ -769,6 +781,7 @@ echo "/* Automatically generated by configure - do not modify */" > $config_h
|
||||
echo "include ../config-host.mak" >> $config_mak
|
||||
echo "#include \"../config-host.h\"" >> $config_h
|
||||
|
||||
bflt="no"
|
||||
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
|
||||
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
|
||||
|
||||
@@ -789,6 +802,7 @@ elif test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
|
||||
echo "TARGET_ARCH=arm" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"arm\"" >> $config_h
|
||||
echo "#define TARGET_ARM 1" >> $config_h
|
||||
bflt="yes"
|
||||
elif test "$target_cpu" = "sparc" ; then
|
||||
echo "TARGET_ARCH=sparc" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"sparc\"" >> $config_h
|
||||
@@ -819,10 +833,13 @@ elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then
|
||||
echo "TARGET_ARCH=mips" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"mips\"" >> $config_h
|
||||
echo "#define TARGET_MIPS 1" >> $config_h
|
||||
elif test "$target_cpu" = "sh4" ; then
|
||||
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
|
||||
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
|
||||
elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
|
||||
echo "TARGET_ARCH=sh4" >> $config_mak
|
||||
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
|
||||
echo "#define TARGET_SH4 1" >> $config_h
|
||||
bflt="yes"
|
||||
else
|
||||
echo "Unsupported target CPU"
|
||||
exit 1
|
||||
@@ -844,10 +861,14 @@ if expr $target : '.*-dm' > /dev/null ; then
|
||||
echo "#define CONFIG_DM 1" >> $config_h
|
||||
fi
|
||||
|
||||
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
|
||||
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
|
||||
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
|
||||
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
|
||||
fi
|
||||
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
|
||||
echo "TARGET_HAS_BFLT=yes" >> $config_mak
|
||||
echo "#define TARGET_HAS_BFLT 1" >> $config_h
|
||||
fi
|
||||
# sdl defines
|
||||
|
||||
if test "$target_user_only" = "no"; then
|
||||
|
||||
+126
-44
@@ -27,8 +27,8 @@
|
||||
#define DEFAULT_BACKSCROLL 512
|
||||
#define MAX_CONSOLES 12
|
||||
|
||||
#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
|
||||
#define RGB(r, g, b) RGBA(r, g, b, 0xff)
|
||||
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
|
||||
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
|
||||
|
||||
typedef struct TextAttributes {
|
||||
uint8_t fgcol:4;
|
||||
@@ -53,6 +53,57 @@ enum TTYState {
|
||||
TTY_STATE_CSI,
|
||||
};
|
||||
|
||||
typedef struct QEMUFIFO {
|
||||
uint8_t *buf;
|
||||
int buf_size;
|
||||
int count, wptr, rptr;
|
||||
} QEMUFIFO;
|
||||
|
||||
int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
|
||||
{
|
||||
int l, len;
|
||||
|
||||
l = f->buf_size - f->count;
|
||||
if (len1 > l)
|
||||
len1 = l;
|
||||
len = len1;
|
||||
while (len > 0) {
|
||||
l = f->buf_size - f->wptr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
memcpy(f->buf + f->wptr, buf, l);
|
||||
f->wptr += l;
|
||||
if (f->wptr >= f->buf_size)
|
||||
f->wptr = 0;
|
||||
buf += l;
|
||||
len -= l;
|
||||
}
|
||||
f->count += len1;
|
||||
return len1;
|
||||
}
|
||||
|
||||
int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
|
||||
{
|
||||
int l, len;
|
||||
|
||||
if (len1 > f->count)
|
||||
len1 = f->count;
|
||||
len = len1;
|
||||
while (len > 0) {
|
||||
l = f->buf_size - f->rptr;
|
||||
if (l > len)
|
||||
l = len;
|
||||
memcpy(buf, f->buf + f->rptr, l);
|
||||
f->rptr += l;
|
||||
if (f->rptr >= f->buf_size)
|
||||
f->rptr = 0;
|
||||
buf += l;
|
||||
len -= l;
|
||||
}
|
||||
f->count -= len1;
|
||||
return len1;
|
||||
}
|
||||
|
||||
/* ??? This is mis-named.
|
||||
It is used for both text and graphical consoles. */
|
||||
struct TextConsole {
|
||||
@@ -81,8 +132,13 @@ struct TextConsole {
|
||||
int nb_esc_params;
|
||||
|
||||
/* kbd read handler */
|
||||
IOCanRWHandler *fd_can_read;
|
||||
IOReadHandler *fd_read;
|
||||
void *fd_opaque;
|
||||
/* fifo for key pressed */
|
||||
QEMUFIFO out_fifo;
|
||||
uint8_t out_fifo_buf[16];
|
||||
QEMUTimer *kbd_timer;
|
||||
};
|
||||
|
||||
static TextConsole *active_console;
|
||||
@@ -274,24 +330,24 @@ enum color_names {
|
||||
|
||||
static const uint32_t color_table_rgb[2][8] = {
|
||||
{ /* dark */
|
||||
RGB(0x00, 0x00, 0x00), /* black */
|
||||
RGB(0xaa, 0x00, 0x00), /* red */
|
||||
RGB(0x00, 0xaa, 0x00), /* green */
|
||||
RGB(0xaa, 0xaa, 0x00), /* yellow */
|
||||
RGB(0x00, 0x00, 0xaa), /* blue */
|
||||
RGB(0xaa, 0x00, 0xaa), /* magenta */
|
||||
RGB(0x00, 0xaa, 0xaa), /* cyan */
|
||||
RGB(0xaa, 0xaa, 0xaa), /* white */
|
||||
QEMU_RGB(0x00, 0x00, 0x00), /* black */
|
||||
QEMU_RGB(0xaa, 0x00, 0x00), /* red */
|
||||
QEMU_RGB(0x00, 0xaa, 0x00), /* green */
|
||||
QEMU_RGB(0xaa, 0xaa, 0x00), /* yellow */
|
||||
QEMU_RGB(0x00, 0x00, 0xaa), /* blue */
|
||||
QEMU_RGB(0xaa, 0x00, 0xaa), /* magenta */
|
||||
QEMU_RGB(0x00, 0xaa, 0xaa), /* cyan */
|
||||
QEMU_RGB(0xaa, 0xaa, 0xaa), /* white */
|
||||
},
|
||||
{ /* bright */
|
||||
RGB(0x00, 0x00, 0x00), /* black */
|
||||
RGB(0xff, 0x00, 0x00), /* red */
|
||||
RGB(0x00, 0xff, 0x00), /* green */
|
||||
RGB(0xff, 0xff, 0x00), /* yellow */
|
||||
RGB(0x00, 0x00, 0xff), /* blue */
|
||||
RGB(0xff, 0x00, 0xff), /* magenta */
|
||||
RGB(0x00, 0xff, 0xff), /* cyan */
|
||||
RGB(0xff, 0xff, 0xff), /* white */
|
||||
QEMU_RGB(0x00, 0x00, 0x00), /* black */
|
||||
QEMU_RGB(0xff, 0x00, 0x00), /* red */
|
||||
QEMU_RGB(0x00, 0xff, 0x00), /* green */
|
||||
QEMU_RGB(0xff, 0xff, 0x00), /* yellow */
|
||||
QEMU_RGB(0x00, 0x00, 0xff), /* blue */
|
||||
QEMU_RGB(0xff, 0x00, 0xff), /* magenta */
|
||||
QEMU_RGB(0x00, 0xff, 0xff), /* cyan */
|
||||
QEMU_RGB(0xff, 0xff, 0xff), /* white */
|
||||
}
|
||||
};
|
||||
|
||||
@@ -563,7 +619,6 @@ static void console_put_lf(TextConsole *s)
|
||||
TextCell *c;
|
||||
int x, y1;
|
||||
|
||||
s->x = 0;
|
||||
s->y++;
|
||||
if (s->y >= s->height) {
|
||||
s->y = s->height - 1;
|
||||
@@ -712,15 +767,12 @@ static void console_putchar(TextConsole *s, int ch)
|
||||
console_put_lf(s);
|
||||
break;
|
||||
case '\b': /* backspace */
|
||||
if(s->x > 0) s->x--;
|
||||
y1 = (s->y_base + s->y) % s->total_height;
|
||||
c = &s->cells[y1 * s->width + s->x];
|
||||
c->ch = ' ';
|
||||
c->t_attrib = s->t_attrib;
|
||||
update_xy(s, s->x, s->y);
|
||||
if (s->x > 0)
|
||||
s->x--;
|
||||
break;
|
||||
case '\t': /* tabspace */
|
||||
if (s->x + (8 - (s->x % 8)) > s->width) {
|
||||
s->x = 0;
|
||||
console_put_lf(s);
|
||||
} else {
|
||||
s->x = s->x + (8 - (s->x % 8));
|
||||
@@ -739,8 +791,10 @@ static void console_putchar(TextConsole *s, int ch)
|
||||
c->t_attrib = s->t_attrib;
|
||||
update_xy(s, s->x, s->y);
|
||||
s->x++;
|
||||
if (s->x >= s->width)
|
||||
if (s->x >= s->width) {
|
||||
s->x = 0;
|
||||
console_put_lf(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -835,6 +889,7 @@ static void console_chr_add_read_handler(CharDriverState *chr,
|
||||
IOReadHandler *fd_read, void *opaque)
|
||||
{
|
||||
TextConsole *s = chr->opaque;
|
||||
s->fd_can_read = fd_can_read;
|
||||
s->fd_read = fd_read;
|
||||
s->fd_opaque = opaque;
|
||||
}
|
||||
@@ -854,6 +909,28 @@ static void console_send_event(CharDriverState *chr, int event)
|
||||
}
|
||||
}
|
||||
|
||||
static void kbd_send_chars(void *opaque)
|
||||
{
|
||||
TextConsole *s = opaque;
|
||||
int len;
|
||||
uint8_t buf[16];
|
||||
|
||||
len = s->fd_can_read(s->fd_opaque);
|
||||
if (len > s->out_fifo.count)
|
||||
len = s->out_fifo.count;
|
||||
if (len > 0) {
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
qemu_fifo_read(&s->out_fifo, buf, len);
|
||||
s->fd_read(s->fd_opaque, buf, len);
|
||||
}
|
||||
/* characters are pending: we send them a bit later (XXX:
|
||||
horrible, should change char device API) */
|
||||
if (s->out_fifo.count > 0) {
|
||||
qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* called when an ascii key is pressed */
|
||||
void kbd_put_keysym(int keysym)
|
||||
{
|
||||
@@ -879,25 +956,26 @@ void kbd_put_keysym(int keysym)
|
||||
console_scroll(10);
|
||||
break;
|
||||
default:
|
||||
if (s->fd_read) {
|
||||
/* convert the QEMU keysym to VT100 key string */
|
||||
q = buf;
|
||||
if (keysym >= 0xe100 && keysym <= 0xe11f) {
|
||||
*q++ = '\033';
|
||||
*q++ = '[';
|
||||
c = keysym - 0xe100;
|
||||
if (c >= 10)
|
||||
*q++ = '0' + (c / 10);
|
||||
*q++ = '0' + (c % 10);
|
||||
*q++ = '~';
|
||||
} else if (keysym >= 0xe120 && keysym <= 0xe17f) {
|
||||
*q++ = '\033';
|
||||
*q++ = '[';
|
||||
*q++ = keysym & 0xff;
|
||||
} else {
|
||||
/* convert the QEMU keysym to VT100 key string */
|
||||
q = buf;
|
||||
if (keysym >= 0xe100 && keysym <= 0xe11f) {
|
||||
*q++ = '\033';
|
||||
*q++ = '[';
|
||||
c = keysym - 0xe100;
|
||||
if (c >= 10)
|
||||
*q++ = '0' + (c / 10);
|
||||
*q++ = '0' + (c % 10);
|
||||
*q++ = '~';
|
||||
} else if (keysym >= 0xe120 && keysym <= 0xe17f) {
|
||||
*q++ = '\033';
|
||||
*q++ = '[';
|
||||
*q++ = keysym & 0xff;
|
||||
} else {
|
||||
*q++ = keysym;
|
||||
}
|
||||
s->fd_read(s->fd_opaque, buf, q - buf);
|
||||
}
|
||||
if (s->fd_read) {
|
||||
qemu_fifo_write(&s->out_fifo, buf, q - buf);
|
||||
kbd_send_chars(s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -984,6 +1062,10 @@ CharDriverState *text_console_init(DisplayState *ds)
|
||||
chr->chr_add_read_handler = console_chr_add_read_handler;
|
||||
chr->chr_send_event = console_send_event;
|
||||
|
||||
s->out_fifo.buf = s->out_fifo_buf;
|
||||
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
|
||||
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
|
||||
|
||||
if (!color_inited) {
|
||||
color_inited = 1;
|
||||
set_color_table(ds);
|
||||
|
||||
Loaded 100 of 368 files, more files were not shown because too many files have changed in this diff.
Show more