From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from aserp2120.oracle.com (aserp2120.oracle.com [141.146.126.78]) by mx.groups.io with SMTP id smtpd.web08.2552.1614113217619651884 for ; Tue, 23 Feb 2021 12:46:57 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@oracle.com header.s=corp-2020-01-29 header.b=pUQZHKVt; spf=pass (domain: oracle.com, ip: 141.146.126.78, mailfrom: ankur.a.arora@oracle.com) Received: from pps.filterd (aserp2120.oracle.com [127.0.0.1]) by aserp2120.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 11NKiQSm158274; Tue, 23 Feb 2021 20:46:54 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.com; h=subject : to : cc : references : from : message-id : date : in-reply-to : content-type : content-transfer-encoding : mime-version; s=corp-2020-01-29; bh=GhRPKrT44QlYZZ+FXo0XHTrHQljKgu1IuhuSOzzqLAk=; b=pUQZHKVtDyY/D4mqMBiYO+Xevk7Szc4TGjitMklA4mRrheQa4afZZfRXHfwpYbcanxnr 8pZWsk+ZtWqsRPgil+vaFk+of280CCh20kezkLGEcGP37a6lNRnJ8El/DBCyEal5ZB0V 2il42vYp4435zdFqUtS3yPZT6OC9mJq9rNTQ8iCcQinDRckoPQFop20PC3iEDSYLeAbi E35oWVX5mRqUikX0gR29WomTDMrlBivMKj9F9o7Q5AL4DD8JeeoYvkflotdl4ls5wVA3 IBH91kTs8g4joh8eMMJX+eZURPp9/uoLsSyJyJUbFtEMd1JXps3HD6vulgnzM7TErkcQ Gw== Received: from userp3030.oracle.com (userp3030.oracle.com [156.151.31.80]) by aserp2120.oracle.com with ESMTP id 36ttcm8snd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 23 Feb 2021 20:46:53 +0000 Received: from pps.filterd (userp3030.oracle.com [127.0.0.1]) by userp3030.oracle.com (8.16.0.42/8.16.0.42) with SMTP id 11NKeVx2039637; Tue, 23 Feb 2021 20:46:52 GMT Received: from nam11-dm6-obe.outbound.protection.outlook.com (mail-dm6nam11lp2176.outbound.protection.outlook.com [104.47.57.176]) by userp3030.oracle.com with ESMTP id 36ucby0geg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 23 Feb 2021 20:46:52 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=MnVL7XdlMw/JAxA8s86bnO8wKp0KcdPJT12HWBZl43VvwY3Cc6Pwk3pltFpxe5rDxqE3nZESstNghwdYucYrrTlEhilnhr4lm1ek/UB2rv4f5835ZAJqZQY3HeV1ZAQZzUBmofkeyNi81sPUppC2fULNC4S4cXC0XmJNwL7+gd12J7vKaxZFidnEOv0qgusimVZYacrm3i9QnWFCqUMw0kDPM+PHC9qGFFjb7dSCTjzRTfyI4jM8su4GTALqrmhKRYcfLZ2Rq+S1gO3tkGOFGtXMlCC+zL+jnHRUTdhoG72mgRUH37+pfgxUxY+0sgunWNOF69Whbc1WcbHi3OfEFA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=GhRPKrT44QlYZZ+FXo0XHTrHQljKgu1IuhuSOzzqLAk=; b=YWJJ2N4EsyUtg1XzvdY/DdDascsY39jA7bcdV6cty/oJ8GfhcRUklGg6L/uuuZ7sXe0n1/guIun+bTU1GZX+U60DFuovQWiFuqncMfyZDEf2cozszMm8FVA1AYVL4x+ZfWdCl1Kl+BDf0PLydIZQSrMQpl4YHtMhVWc8NDVltDIxdIuslOqfdOP9QoM9wcvfkPJtQC4zBCG8h4pK07sI076WMB0wgeB3P+iQoRBR9V6Us5yGrkuRqSg+mlS0hH2fr8cPE9bX7GMdP8DFLJImEmsrucpKzJeHvnszPAbYSmVmHNqiXH7BRqnJ3zzPSzSKd9X0KDO/hpghkDOexdlqAQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oracle.com; dmarc=pass action=none header.from=oracle.com; dkim=pass header.d=oracle.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oracle.onmicrosoft.com; s=selector2-oracle-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=GhRPKrT44QlYZZ+FXo0XHTrHQljKgu1IuhuSOzzqLAk=; b=z7C1LxVtSPII6kgpoveigL4nm3IZPKotyqGMq+I2pHCUsczW0VSdeLJUcNhgKDWCr0cnaDcqFbKQJ5YRCG0xLRm5x3xQ8NkZW+uI3xhKHVU28RNvXlL5DKbc10Y7W8yJ5uF+W6kLLtoBAnql+xxcC5EP5T3EQG21YQG0mZLM4es= Received: from SJ0PR10MB4605.namprd10.prod.outlook.com (2603:10b6:a03:2d9::24) by BYAPR10MB3144.namprd10.prod.outlook.com (2603:10b6:a03:15c::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3868.29; Tue, 23 Feb 2021 20:46:50 +0000 Received: from SJ0PR10MB4605.namprd10.prod.outlook.com ([fe80::a021:790:7ce6:6f16]) by SJ0PR10MB4605.namprd10.prod.outlook.com ([fe80::a021:790:7ce6:6f16%6]) with mapi id 15.20.3868.033; Tue, 23 Feb 2021 20:46:50 +0000 Subject: Re: [edk2-devel] [PATCH v8 07/10] OvmfPkg/SmmCpuFeaturesLib: call CPU hot-eject handler To: Paolo Bonzini , Laszlo Ersek , devel@edk2.groups.io Cc: imammedo@redhat.com, boris.ostrovsky@oracle.com, Jordan Justen , Ard Biesheuvel , Aaron Young References: <20210222071928.1401820-1-ankur.a.arora@oracle.com> <20210222071928.1401820-8-ankur.a.arora@oracle.com> <746e09c5-8623-d1fe-5871-0960abf09579@redhat.com> <36d02edb-088e-5276-1a6e-435b5417e82c@redhat.com> From: "Ankur Arora" Message-ID: Date: Tue, 23 Feb 2021 12:46:46 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.6.0 In-Reply-To: <36d02edb-088e-5276-1a6e-435b5417e82c@redhat.com> X-Originating-IP: [148.87.23.8] X-ClientProxiedBy: CO2PR05CA0007.namprd05.prod.outlook.com (2603:10b6:102:2::17) To SJ0PR10MB4605.namprd10.prod.outlook.com (2603:10b6:a03:2d9::24) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from [192.168.0.108] (148.87.23.8) by CO2PR05CA0007.namprd05.prod.outlook.com (2603:10b6:102:2::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3890.8 via Frontend Transport; Tue, 23 Feb 2021 20:46:49 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 1ebaffd3-585d-4cbc-4b58-08d8d83c24ee X-MS-TrafficTypeDiagnostic: BYAPR10MB3144: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: EWuyxO2mDcw8UpaJzt7AlauYhgl5wHkQP5SgHxfTShAztqHbneLMDF0gNrBr7eBywWVF7qP/nl5L1+EcFEE9vfB8zFlUC2C5rB1/UMTye2gYSkSlhAkoeH9iUKsn6gTmLoCaKsZN9jph+b0TqZKS8GhZo+036LyMflGPOsnSDnObRIZ24QsypuShvVmXYB9OOMKln2Qj1t0unN7JF9DTatYFxp4Jpfgp8iJusSYJiJWdtrEDQsDJFDy9KE12KE6h/Wj1Kt+IqXWmxYrRkuzkuq73pkeHT/eh2e+UrSdExRHbxfiVQiTi+CMPbOJwpGywYgIwBFmH7MYDIMUvDb7DwaTWNTMHZkB4Flrw8U99QZyCpiSM4e9tVl0dWlvq+tHQcNxgL1RcQEaycfD53RxjQorx/e8vL6BkyptbgVQcxgEJecYYPF4Lpduq+PgpwxGWvYg5jeq5WgV8YxdLuFoJWarLmaiIxzHgH9N+X7tkNB7+wLElZt2UF+nufgVJ+Jq2YQN61segGxoWOD7lXZ2IFR9wNXnumECyyt2iFcVYpORY/zlvuABC7VFyK2RMkT5xnFDjdwmnwTG6vuZ/ZoA2An4THwbqMeNIhG7pDFzc4Ag= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:SJ0PR10MB4605.namprd10.prod.outlook.com;PTR:;CAT:NONE;SFS:(39860400002)(366004)(136003)(346002)(376002)(396003)(16526019)(107886003)(186003)(31696002)(8936002)(6486002)(66946007)(4326008)(53546011)(8676002)(54906003)(956004)(110136005)(36756003)(2616005)(31686004)(478600001)(86362001)(66476007)(5660300002)(66556008)(26005)(2906002)(16576012)(316002)(6666004)(45980500001)(43740500002);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: =?utf-8?B?aWU1Q2p6aGRnZlozdlUyL1JvN3JOaW92MExDS0R2bVlVMFJ3akhvbzRLTzVW?= =?utf-8?B?L2Y1eE5DVlY4TGNYWEhyeGNVcXQrTWE2SHp2SzVRc0J4UTRoZ09UVFdHa1Nr?= =?utf-8?B?V0svc05wNTJCbW1UWFBzd001TkxkZVJkOG9JM3dwemM2RkhxVnNRN1hVQjhX?= =?utf-8?B?ejdRSllvdStzWXN3UmEvSmNBeXdBaDR0dm5wbGQ5aWdtOGNKbm02Q3NvMTFn?= =?utf-8?B?RE42K1BWemxNcnpKajdKR2JOTGxCZXNIQ09HSTkrK0lsOS9YSndJL3BqNk9u?= =?utf-8?B?WExHQXl6UXJnMDRuMHhsaTIyMW0yZysxaFhQNExMOWx5MFB5ZXJGaE4wTTBH?= =?utf-8?B?cFdUV2doNXc3WG41R3plRGRrTFU5ejlCQUdoeVlJWitlN1c4MTdKbm94Y3Nj?= =?utf-8?B?NUtEK291K2NXSFVuaDMwMnozWXZmUkZ1bGRXR2g2cUlxVEl0SkJjNzB4a1BQ?= =?utf-8?B?QkU5d0NydlVHWlk2djhTb1QwajJ2eFBvRlhzSVNCbE5lWXZialpEd0ZnQ1Rk?= =?utf-8?B?SUVvcFpsKy9zalFXZFhlWmdIVmRlNVJ4Uk5tTTNvMFpOeC8reFNQNlArbDRv?= =?utf-8?B?SDlNVUxIZmMreERzSUM2YnJVcnBaVWwvRW5DUWQvbnFBbDVkdUR5UDNycUIx?= =?utf-8?B?YjUxK29SdFl6YW0wWlRrM3ptSDd2ZVNNOXFvZlczYjI5c2NlNGk1NGduT1d6?= =?utf-8?B?TVZhSkt6QXdiMjZKVWNZR2tNOWJHZ0NuVjJ3bDlQVnZTYno0WUFtQ3hwRHZx?= =?utf-8?B?SDhFdjdHUVZSYnpwV2YwQ0R3NTduUnVpU1czQWMrbng5NElCZWhRdkYyNGFw?= =?utf-8?B?cFIvWEwrcm5qTE1iT0JId2g4ek4vVm0wZzcvWDR5aTk4Vlg3ZmRTTDlhZm5y?= =?utf-8?B?M25BU1lUSkdHc2J5aCtUUUM5bEd3SXk2WDlTSlpyUUgvNVVxbjgwVEhtOU1Y?= =?utf-8?B?Sk9XNWxqUktGSTlmREVDNlpCekx1cDZldjAycWxVcXRxUTdUM2crc0R3YVg3?= =?utf-8?B?NTdERUpNMFdUVzBjTkdmQzI5akI1NytjYWZQeDhjTFAxMDZIR3ZCdkxqOWpG?= =?utf-8?B?U0M4Nld6R0xibEU1M1hRcW10SHZEbXo0UkZ6TEpNRDV1aWtUQ0tabDZXeWtz?= =?utf-8?B?TWNsN2hWOVIya3A4V3hPMUt2Vyt1SDVudUFwOWlpZFlDUU42UGdsazl3Zm5X?= =?utf-8?B?MGovYlVoOWxjZFNsTmdPaGZsTmhydit5QjgvaWlEdXRqYWNaZGlqa1FNZVhM?= =?utf-8?B?NWZtc1hrZCtmMHpzMnlkRUMwZDZVSjM4djhZamt5RU5JQW5UVE9RZVJPVlhW?= =?utf-8?B?Q3FlWmFmOHZoWjI3TWxhTUFkaDVFaEZJTUtwU25NT0FOdXZMUFJLS1hYRXNh?= =?utf-8?B?Ykp1d3BmNjZ2cnFlQy9Vak9iZ3RtbGd1VUFKcWdRcWV5U1I3ZTl1SFVuZFFt?= =?utf-8?B?TlR4UjJRdEtNQ1J0dFpPVjdzdkUwZFlKTzFnT2pZNmg0ZjhkTmFudnRrVjhO?= =?utf-8?B?ZXRaeG9PbVg0SG9jazRtWGVvVmJHWG5jeGlWeVE2Sm5ORFpURTRQMnk3cXZ4?= =?utf-8?B?TkowR3dyRXFkbElkcDhMdGs3MWxyQ0U2RUNTa3JiaHE3dklQeVZHWnpYT2hR?= =?utf-8?B?eHVKU25kU1VWeDg3M3dDTHlNWk1HYnRja1lUN0pyRDhrQXFOS3JaV3dpYi9C?= =?utf-8?B?MGptWVkyOGtSc2VJV2pualNzQ3FDeWhvbFRlZ2JSamRWeHkxRURRVUZaYlll?= =?utf-8?Q?bTXj4H4hEAJedwQcQ9wEUS4mKSkQl/tsu77a63e?= X-OriginatorOrg: oracle.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1ebaffd3-585d-4cbc-4b58-08d8d83c24ee X-MS-Exchange-CrossTenant-AuthSource: SJ0PR10MB4605.namprd10.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 23 Feb 2021 20:46:50.3403 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 4e2c6054-71cb-48f1-bd6c-3a9705aca71b X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 1ZZhZfmZ1Wjq4kmVVRTVyGv0LGlY2tlJPQoLas+srNQbe7grDzPpFA0mY1NZeR/0p4klwcPVguAJMASIwmIRUD+OxqweVGhKYwT8l4yN/ps= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BYAPR10MB3144 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=9904 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 adultscore=0 phishscore=0 spamscore=0 suspectscore=0 bulkscore=0 malwarescore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2102230175 X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=9904 signatures=668683 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 mlxlogscore=999 adultscore=0 lowpriorityscore=0 spamscore=0 mlxscore=0 bulkscore=0 clxscore=1015 priorityscore=1501 malwarescore=0 impostorscore=0 suspectscore=0 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2009150000 definitions=main-2102230175 X-MIME-Autoconverted: from 8bit to quoted-printable by aserp2120.oracle.com id 11NKiQSm158274 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable On 2021-02-23 9:18 a.m., Paolo Bonzini wrote: > On 23/02/21 18:06, Laszlo Ersek wrote: >> On 02/23/21 08:45, Paolo Bonzini wrote: >>> On 22/02/21 15:53, Laszlo Ersek wrote: >>>>> + >>>>> +=C2=A0 if (mCpuHotEjectData !=3D NULL) { >>>>> +=C2=A0=C2=A0=C2=A0 CPU_HOT_EJECT_HANDLER Handler; >>>>> + >>>>> +=C2=A0=C2=A0=C2=A0 Handler =3D mCpuHotEjectData->Handler; >>>> This patch looks otherwise OK to me, but: >>>> >>>> In patch v8 08/10, we have a ReleaseMemoryFence(). (For now, it is o= nly >>>> expressed as a MemoryFence() call; we'll make that more precise late= r.) >>>> >>>> (1) I think that should be paired with an AcquireMemoryFence() call, >>>> just before loading "mCpuHotEjectData->Handler" above -- for now, al= so >>>> expressed as a MemoryFence() call only. >>> >>> In Linux terms, there is a control dependency here.=C2=A0 However, it= should >>> at least be a separate statement to load mCpuHotEjectData (which from= my >>> EDK2 reminiscences should be a global) into a local variable.=C2=A0 S= o >>> >>> =C2=A0=C2=A0 EjectData =3D mCPUHotEjectData; >>> =C2=A0=C2=A0 // Optional AcquireMemoryFence here >>> =C2=A0=C2=A0 if (EjectData !=3D NULL) { >>> =C2=A0=C2=A0=C2=A0=C2=A0 CPU_HOT_EJECT_HANDLER Handler; >>> >>> =C2=A0=C2=A0=C2=A0=C2=A0 Handler =3D EjectData->Handler; >>> =C2=A0=C2=A0=C2=A0=C2=A0 if (Handler !=3D NULL) { >>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Handler (CpuIndex); >>> =C2=A0=C2=A0=C2=A0=C2=A0 } >>> =C2=A0=C2=A0 } >> >> Yes, "mCPUHotEjectData" is a global. >> >> "mCpuHotEjectData" itself is set up on the BSP (from the entry point >> function of the PiSmmCpuSmmDxe driver), before any other APs have a >> chance to execute any SMM-related code at all. Furthermore, once set u= p, >> mCpuHotEjectData never changes -- it remains set to a particular >> non-NULL value forever, or it remains NULL forever. (The latter case >> applies when the possible CPU count is 1; IOW, then there is no AP at = all.) >=20 > Ok, that's what I was missing.=C2=A0 However, your code below has *two*= loads of mCpuHotEjectData and the fence would have to go after the secon= d (between the load of mCpuHotEjectData and the load of the Handler field= ).=C2=A0 Therefore I would still use a local variable even if you decide = to put the fence inside the "if", which I agree is the clearest. Sorry, I'm missing something here. As Laszlo said given that mCpuHotEject= Data does not change after being set, so why would it be a problem in referenc= ing it twice? The generated code looks like this (load for mCpuHotEjectData at 0xf54b a= nd then the dependent mCpuHotEjectData->Handler load on 0xf645): # 17d60 f54b: 48 8b 05 0e 88 00 00 mov 0x880e(%rip),%rax f54e: R_X86_64_PC32 .data+0x1d5c f552: 48 85 c0 test %rax,%rax f555: 0f 85 ea 00 00 00 jne f645 # Handler =3D mCpuHotEjectData->Handler f645: 48 8b 40 08 mov 0x8(%rax),%rax f649: 48 85 c0 test %rax,%rax f64c: 74 05 je f653 f64e: 4c 89 e1 mov %r12,%rcx f651: ff d0 callq *%rax In the worst case, however, maybe it looks like this (two loads for mCpuHotEjectData and then the dependent load): # 17d60 f54b: 48 8b 05 0e 88 00 00 mov 0x880e(%rip),%rax f54e: R_X86_64_PC32 .data+0x1d5c f552: 48 85 c0 test %rax,%rax f555: 0f 85 ea 00 00 00 jne f645 # 17d60 f645: 48 8b 05 0e 88 00 00 mov 0x880e(%rip),%rax +3: R_X86_64_PC32 .data+0x1d5c # Handler =3D mCpuHotEjectData->Handler +7: 48 8b 40 08 mov 0x8(%rax),%rax +11: 48 85 c0 test %rax,%rax +14: 74 05 je f653 +16: 4c 89 e1 mov %r12,%rcx +19: ff d0 callq *%rax As you and Laszlo say -- we do need an acquire fence before this line (which corresponds to the release fence in UnplugCpus(), patch 8 and the release fence in EjectCpu() in patch 9). # Handler =3D mCpuHotEjectData->Handler 48 8b 40 08 mov 0x8(%rax),%rax A local variable for mCpuHotEjectData, would be nice to have but I'm not sure it is needed for correctness. Ankur =20 > Paolo >=20 >> Because of that, I thought that the first comparison (mCpuHotEjectData >> !=3D NULL) would not need any fence -- I thought it was similar to a >> userspace program that (a) set a global variable in the "main" thread, >> before calling pthread_create(), (b) treated the global variable as a >> constant, ever after (meaning all threads). >> >> However, mCpuHotEjectData->Handler is changed regularly (modified by t= he >> BSP, and read "later" by all processors). That's why I thought the >> acquire fence was needed in the following location: >> >> =C2=A0=C2=A0 if (mCpuHotEjectData !=3D NULL) { >> =C2=A0=C2=A0=C2=A0=C2=A0 CPU_HOT_EJECT_HANDLER Handler; >> >> =C2=A0=C2=A0=C2=A0=C2=A0 // >> =C2=A0=C2=A0=C2=A0=C2=A0 // HERE -- AcquireMemoryFence() >> =C2=A0=C2=A0=C2=A0=C2=A0 // >> =C2=A0=C2=A0=C2=A0=C2=A0 Handler =3D mCpuHotEjectData->Handler; >> =C2=A0=C2=A0=C2=A0=C2=A0 if (Handler !=3D NULL) { >> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Handler (CpuIndex); >> =C2=A0=C2=A0=C2=A0=C2=A0 } >> =C2=A0=C2=A0 } >> >> Thanks! >> Laszlo >> >=20