From mboxrd@z Thu Jan 1 00:00:00 1970 From: Peter Maydell Subject: Re: [PATCH v9 4/6] target-arm: kvm - add support for HW assisted debug Date: Fri, 20 Nov 2015 15:48:28 +0000 Message-ID: References: <1447345251-22625-1-git-send-email-alex.bennee@linaro.org> <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Cc: kvm-devel , Marc Zyngier , QEMU Developers , qemu-arm@nongnu.org, Zhichao Huang , Paolo Bonzini , "kvmarm@lists.cs.columbia.edu" , arm-mail-list To: =?UTF-8?B?QWxleCBCZW5uw6ll?= Return-path: In-Reply-To: <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kvmarm-bounces@lists.cs.columbia.edu Sender: kvmarm-bounces@lists.cs.columbia.edu List-Id: kvm.vger.kernel.org T24gMTIgTm92ZW1iZXIgMjAxNSBhdCAxNjoyMCwgQWxleCBCZW5uw6llIDxhbGV4LmJlbm5lZUBs aW5hcm8ub3JnPiB3cm90ZToKPiBUaGlzIGFkZHMgYmFzaWMgc3VwcG9ydCBmb3IgSFcgYXNzaXN0 ZWQgZGVidWcuIFRoZSBpb2N0bCBpbnRlcmZhY2UgdG8KPiBLVk0gYWxsb3dzIHVzIHRvIHBhc3Mg YW4gaW1wbGVtZW50YXRpb24gZGVmaW5lZCBudW1iZXIgb2YgYnJlYWsgYW5kCj4gd2F0Y2ggcG9p bnQgcmVnaXN0ZXJzLiBXaGVuIEtWTV9HVUVTVERCR19VU0VfSFcgaXMgc3BlY2lmaWVkIHRoZXNl Cj4gZGVidWcgcmVnaXN0ZXJzIHdpbGwgYmUgaW5zdGFsbGVkIGluIHBsYWNlIG9uIHRoZSB3b3Js ZCBzd2l0Y2ggaW50byB0aGUKPiBndWVzdC4KPgo+IFRoZSBoYXJkd2FyZSBpcyBhY3R1YWxseSBj YXBhYmxlIG9mIG1vcmUgYWR2YW5jZWQgbWF0Y2hpbmcgYnV0IGl0IGlzCj4gdW5jbGVhciBpZiB0 aGlzIGV4cHJlc3NpdmVuZXNzIGlzIGF2YWlsYWJsZSB2aWEgdGhlIGdkYnN0dWIgcHJvdG9jb2wu Cj4KPiBTaWduZWQtb2ZmLWJ5OiBBbGV4IEJlbm7DqWUgPGFsZXguYmVubmVlQGxpbmFyby5vcmc+ Cj4KPiAtLS0KPiB2Mgo+ICAgLSBjb3JyZWN0IHNldHRpbmcgb2YgUE1DL0JBUy9NQVNLCj4gICAt IGltcHJvdmVkIGNvbW1lbnRhcnkKPiAgIC0gYWRkZWQgaGVscGVyIGZ1bmN0aW9uIHRvIGNoZWNr IHdhdGNocG9pbnQgaW4gcmFuZ2UKPiAgIC0gZml4IGZpbmQvZGVsZXRpb24gb2Ygd2F0Y2hwb2lu dHMKPiB2Mwo+ICAgLSB1c2UgaW50ZXJuYWxzLmggZGVmaW5pdGlvbnMKPiB2Ngo+ICAgLSBLVk1f R1VFU1REQkdfVVNFX0hXX0JQLT5LVk1fR1VFU1REQkdfVVNFX0hXCj4gICAtIHJlbmFtZWQgc29t ZSBoZWxwZXIgZnVuY3Rpb25zIHRvIGF2b2lkIGNvbmZ1c2lvbgo+IHY5Cj4gICAtIGZpeCBtZXJn ZSBjb25mbGljdHMgb24gcmUtYmFzZQo+ICAgLSBybSBhc20vcHRyYWNlLmggaW5jbHVkZQo+ICAg LSBhZGQgYWRkaXRpb25hbCBjb21tZW50cnkgZm9yIGh3IGJyZWFrcG9pbnRzCj4gICAtIGV4cGxh aW4gZ2RiJ3MgbW9kZWwgZm9yIEhXIGJrcHRzCj4gICAtIGZpeCB1cCBzcGFjaW5nLCBmb3JtYXR0 aW5nIGFzIHBlciBjaGVja3BhdGNoCj4gICAtIGJldHRlciBQQUMgdmFsdWVzCj4gICAtIHVzZSBp c19wb3dlcl9vZl8yCj4gICAtIHVzZSBfYXJtXyBmbiBuYW1pbmcgYW5kIGFkZCBkb2NzCj4gICAt IGFkZCBhIENQVVdhdGNocG9pbnQgc3RydWN0dXJlIGZvciByZXBvcnRpbmcKPiAgIC0gcmVwbGFj ZSBtYW51YWwgYXJyYXkgbWFuaXB1bGF0aW9uIHdpdGggZ19hcnJheSBhYnN0cmFjdGlvbgo+IC0t LQo+ICB0YXJnZXQtYXJtL2t2bS5jICAgICB8ICAzOCArKystLS0KPiAgdGFyZ2V0LWFybS9rdm02 NC5jICAgfCAzNTIgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKystCj4gIHRhcmdldC1hcm0va3ZtX2FybS5oIHwgIDM4ICsrKysrKwo+ICAzIGZpbGVzIGNo YW5nZWQsIDQwNiBpbnNlcnRpb25zKCspLCAyMiBkZWxldGlvbnMoLSkKPgo+IGRpZmYgLS1naXQg YS90YXJnZXQtYXJtL2t2bS5jIGIvdGFyZ2V0LWFybS9rdm0uYwo+IGluZGV4IGQ1MDVhN2UuLjFm NTdlOTIgMTAwNjQ0Cj4gLS0tIGEvdGFyZ2V0LWFybS9rdm0uYwo+ICsrKyBiL3RhcmdldC1hcm0v a3ZtLmMKPiBAQCAtNTQ3LDYgKzU0NywyMCBAQCBzdGF0aWMgaW50IGt2bV9oYW5kbGVfZGVidWco Q1BVU3RhdGUgKmNzLCBzdHJ1Y3Qga3ZtX3J1biAqcnVuKQo+ICAgICAgICAgICAgICByZXR1cm4g dHJ1ZTsKPiAgICAgICAgICB9Cj4gICAgICAgICAgYnJlYWs7Cj4gKyAgICBjYXNlIEVDX0JSRUFL UE9JTlQ6Cj4gKyAgICAgICAgaWYgKGt2bV9hcm1fZmluZF9od19icmVha3BvaW50KGNzLCBlbnYt PnBjKSkgewo+ICsgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKPiArICAgICAgICB9Cj4gKyAgICAg ICAgYnJlYWs7Cj4gKyAgICBjYXNlIEVDX1dBVENIUE9JTlQ6Cj4gKyAgICB7Cj4gKyAgICAgICAg Q1BVV2F0Y2hwb2ludCAqd3AgPSBrdm1fYXJtX2ZpbmRfaHdfd2F0Y2hwb2ludChjcywgYXJjaF9p bmZvLT5mYXIpOwoKVGhpcyB3b24ndCBjb21waWxlIGZvciAzMi1iaXQgQVJNLgoKPiArICAgICAg ICBpZiAod3ApIHsKPiArICAgICAgICAgICAgY3MtPndhdGNocG9pbnRfaGl0ID0gd3A7Cj4gKyAg ICAgICAgICAgIHJldHVybiB0cnVlOwo+ICsgICAgICAgIH0KPiArICAgICAgICBicmVhazsKPiAr ICAgIH0KPiAgICAgIGRlZmF1bHQ6Cj4gICAgICAgICAgZXJyb3JfcmVwb3J0KCIlczogdW5oYW5k bGVkIGRlYnVnIGV4aXQgKCUiUFJJeDMyIiwgJSJQUkl4NjQiKVxuIiwKPiAgICAgICAgICAgICAg ICAgICAgICAgX19mdW5jX18sIGFyY2hfaW5mby0+aHNyLCBlbnYtPnBjKTsKPiBAQCAtNjA4LDYg KzYyMiwxMCBAQCB2b2lkIGt2bV9hcmNoX3VwZGF0ZV9ndWVzdF9kZWJ1ZyhDUFVTdGF0ZSAqY3Ms IHN0cnVjdCBrdm1fZ3Vlc3RfZGVidWcgKmRiZykKPiAgICAgIGlmIChrdm1fc3dfYnJlYWtwb2lu dHNfYWN0aXZlKGNzKSkgewo+ICAgICAgICAgIGRiZy0+Y29udHJvbCB8PSBLVk1fR1VFU1REQkdf RU5BQkxFIHwgS1ZNX0dVRVNUREJHX1VTRV9TV19CUDsKPiAgICAgIH0KPiArICAgIGlmIChrdm1f YXJtX2h3X2RlYnVnX2FjdGl2ZShjcykpIHsKPiArICAgICAgICBkYmctPmNvbnRyb2wgfD0gS1ZN X0dVRVNUREJHX0VOQUJMRSB8IEtWTV9HVUVTVERCR19VU0VfSFc7Cj4gKyAgICAgICAga3ZtX2Fy bV9jb3B5X2h3X2RlYnVnX2RhdGEoJmRiZy0+YXJjaCk7Cj4gKyAgICB9Cj4gIH0KPgo+ICAvKiBD Ni42LjI5IEJSSyBpbnN0cnVjdGlvbiAqLwo+IEBAIC02MzUsMjYgKzY1Myw2IEBAIGludCBrdm1f YXJjaF9yZW1vdmVfc3dfYnJlYWtwb2ludChDUFVTdGF0ZSAqY3MsIHN0cnVjdCBrdm1fc3dfYnJl YWtwb2ludCAqYnApCj4gICAgICByZXR1cm4gMDsKPiAgfQo+Cj4gLWludCBrdm1fYXJjaF9pbnNl cnRfaHdfYnJlYWtwb2ludCh0YXJnZXRfdWxvbmcgYWRkciwKPiAtICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIHRhcmdldF91bG9uZyBsZW4sIGludCB0eXBlKQo+IC17Cj4gLSAgICBx ZW11X2xvZ19tYXNrKExPR19VTklNUCwgIiVzOiBub3QgaW1wbGVtZW50ZWRcbiIsIF9fZnVuY19f KTsKPiAtICAgIHJldHVybiAtRUlOVkFMOwo+IC19CgpZb3UndmUgbW92ZWQgdGhlc2UgZnVuY3Rp b25zIGludG8ga3ZtNjQuYyBidXQgaGF2ZW4ndCBwcm92aWRlZAphIHN0dWIgdmVyc2lvbiBpbiBr dm0zMi5jLi4uCgo+IC0KPiAtaW50IGt2bV9hcmNoX3JlbW92ZV9od19icmVha3BvaW50KHRhcmdl dF91bG9uZyBhZGRyLAo+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0 X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4gLXsKPiAtICAgIHFlbXVfbG9nX21hc2soTE9HX1VOSU1Q LCAiJXM6IG5vdCBpbXBsZW1lbnRlZFxuIiwgX19mdW5jX18pOwo+IC0gICAgcmV0dXJuIC1FSU5W QUw7Cj4gLX0KPiAtCj4gLQo+IC12b2lkIGt2bV9hcmNoX3JlbW92ZV9hbGxfaHdfYnJlYWtwb2lu dHModm9pZCkKPiAtewo+IC0gICAgcWVtdV9sb2dfbWFzayhMT0dfVU5JTVAsICIlczogbm90IGlt cGxlbWVudGVkXG4iLCBfX2Z1bmNfXyk7Cj4gLX0KPiAtCj4gIHZvaWQga3ZtX2FyY2hfaW5pdF9p cnFfcm91dGluZyhLVk1TdGF0ZSAqcykKPiAgewo+ICB9Cj4gZGlmZiAtLWdpdCBhL3RhcmdldC1h cm0va3ZtNjQuYyBiL3RhcmdldC1hcm0va3ZtNjQuYwo+IGluZGV4IGQwODc3OTQuLmM0NjgzMjQg MTAwNjQ0Cj4gLS0tIGEvdGFyZ2V0LWFybS9rdm02NC5jCj4gKysrIGIvdGFyZ2V0LWFybS9rdm02 NC5jCj4gQEAgLTIsNiArMiw3IEBACj4gICAqIEFSTSBpbXBsZW1lbnRhdGlvbiBvZiBLVk0gaG9v a3MsIDY0IGJpdCBzcGVjaWZpYyBjb2RlCj4gICAqCj4gICAqIENvcHlyaWdodCBNaWFuLU0uIEhh bWF5dW4gMjAxMywgVmlydHVhbCBPcGVuIFN5c3RlbXMKPiArICogQ29weXJpZ2h0IEFsZXggQmVu bsOpZSAyMDE0LCBMaW5hcm8KPiAgICoKPiAgICogVGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVy IHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdQTCwgdmVyc2lvbiAyIG9yIGxhdGVyLgo+ICAgKiBTZWUg dGhlIENPUFlJTkcgZmlsZSBpbiB0aGUgdG9wLWxldmVsIGRpcmVjdG9yeS4KPiBAQCAtMTIsMTIg KzEzLDE3IEBACj4gICNpbmNsdWRlIDxzeXMvdHlwZXMuaD4KPiAgI2luY2x1ZGUgPHN5cy9pb2N0 bC5oPgo+ICAjaW5jbHVkZSA8c3lzL21tYW4uaD4KPiArI2luY2x1ZGUgPHN5cy9wdHJhY2UuaD4K Pgo+ICsjaW5jbHVkZSA8bGludXgvZWxmLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9rdm0uaD4KPgo+ ICAjaW5jbHVkZSAiY29uZmlnLWhvc3QuaCIKPiAgI2luY2x1ZGUgInFlbXUtY29tbW9uLmgiCj4g ICNpbmNsdWRlICJxZW11L3RpbWVyLmgiCj4gKyNpbmNsdWRlICJxZW11L2hvc3QtdXRpbHMuaCIK PiArI2luY2x1ZGUgInFlbXUvZXJyb3ItcmVwb3J0LmgiCj4gKyNpbmNsdWRlICJleGVjL2dkYnN0 dWIuaCIKPiAgI2luY2x1ZGUgInN5c2VtdS9zeXNlbXUuaCIKPiAgI2luY2x1ZGUgInN5c2VtdS9r dm0uaCIKPiAgI2luY2x1ZGUgImt2bV9hcm0uaCIKPiBAQCAtMjcsMjAgKzMzLDM2MiBAQAo+Cj4g IHN0YXRpYyBib29sIGhhdmVfZ3Vlc3RfZGVidWc7Cj4KPiArLyoKPiArICogQWx0aG91Z2ggdGhl IEFSTSBpbXBsZW1lbnRhdGlvbiBvZiBoYXJkd2FyZSBhc3Npc3RlZCBkZWJ1Z2dpbmcKPiArICog YWxsb3dzIGZvciBkaWZmZXJlbnQgYnJlYWtwb2ludHMgcGVyLWNvcmUgdGhlIGN1cnJlbnQgR0RC IGludGVyZmFjZQoKQ29tbWEgYWZ0ZXIgInBlci1jb3JlIi4KCj4gKyAqIHRyZWF0cyB0aGVtIGFz IGEgZ2xvYmFsIHBvb2wgb2YgcmVnaXN0ZXJzICh3aGljaCBzZWVtcyB0byBiZSB0aGUKPiArICog Y2FzZSBmb3IgeDg2LCBwcGMgYW5kIHMzOTApLiBBcyBhIHJlc3VsdCB3ZSBzdG9yZSBvbmUgY29w eSBvZgo+ICsgKiByZWdpc3RlcnMgd2hpY2ggaXMgdXNlZCBmb3IgYWxsIGFjdGl2ZSBjb3Jlcy4K PiArICoKPiArICogV3JpdGUgYWNjZXNzIGlzIHNlcmlhbGlzZWQgYnkgdmlydHVlIG9mIHRoZSBH REIgcHJvdG9jb2wgd2hpY2gKPiArICogdXBkYXRlcyB0aGluZ3MuIFJlYWQgYWNjZXNzIChpLmUu IHdoZW4gdGhlIHZhbHVlcyBhcmUgY29waWVkIHRvIHRoZQo+ICsgKiB2Q1BVKSBpcyBhbHNvIGdh dGVkIGJ5IEdEQnMgcnVuIGNvbnRyb2wuCgoiR0RCJ3MiLgoKPiArICoKPiArICogVGhpcyBpcyBu b3QgdW5yZWFzb25hYmxlIGFzIG1vc3Qgb2YgdGhlIHRpbWUgZGVidWdnaW5nIGtlcm5lbHMgeW91 Cj4gKyAqIG5ldmVyIGtub3cgd2hpY2ggY29yZSB3aWxsIGV2ZW50dWFsbHkgZXhlY3V0ZSB5b3Vy IGZ1bmN0aW9uLgo+ICsgKi8KPiArCj4gK3R5cGVkZWYgc3RydWN0IHsKPiArICAgIHVpbnQ2NF90 IGJjcjsKPiArICAgIHVpbnQ2NF90IGJ2cjsKPiArfSBIV0JyZWFrcG9pbnQ7Cj4gKwo+ICsvKiBU aGUgd2F0Y2hwb2ludCByZWdpc3RlcnMgY2FuIGNvdmVyIG1vcmUgYXJlYSB0aGFuIHRoZSByZXF1 ZXN0ZWQKPiArICogd2F0Y2hwb2ludCBzbyB3ZSBuZWVkIHRvIHN0b3JlIHRoZSBhZGRpdGlvbmFs IGluZm9ybWF0aW9uCj4gKyAqIHNvbWV3aGVyZS4gV2UgYWxzbyBuZWVkIHRvIHN1cHBseSBhIENQ VVdhdGNocG9pbnQgdG8gdGhlIEdEQiBzdHViCj4gKyAqIHdoZW4gdGhlIHdhdGNocG9pbnQgaXMg aGl0Lgo+ICsgKi8KPiArdHlwZWRlZiBzdHJ1Y3Qgewo+ICsgICAgdWludDY0X3Qgd2NyOwo+ICsg ICAgdWludDY0X3Qgd3ZyOwo+ICsgICAgQ1BVV2F0Y2hwb2ludCBkZXRhaWxzOwo+ICt9IEhXV2F0 Y2hwb2ludDsKPiArCj4gKy8qIE1heGltdW0gYW5kIGN1cnJlbnQgYnJlYWsvd2F0Y2ggcG9pbnQg Y291bnRzICovCj4gK2ludCBtYXhfaHdfYnBzLCBtYXhfaHdfd3BzOwo+ICtHQXJyYXkgKmh3X2Jy ZWFrcG9pbnRzLCAqaHdfd2F0Y2hwb2ludHM7Cj4gKwo+ICsjZGVmaW5lIGN1cl9od193cHMgICAg ICAoaHdfd2F0Y2hwb2ludHMtPmxlbikKPiArI2RlZmluZSBjdXJfaHdfYnBzICAgICAgKGh3X2Jy ZWFrcG9pbnRzLT5sZW4pCj4gKyNkZWZpbmUgZ2V0X2h3X2JwKGkpICAgICgmZ19hcnJheV9pbmRl eChod19icmVha3BvaW50cywgSFdCcmVha3BvaW50LCBpKSkKPiArI2RlZmluZSBnZXRfaHdfd3Ao aSkgICAgKCZnX2FycmF5X2luZGV4KGh3X3dhdGNocG9pbnRzLCBIV1dhdGNocG9pbnQsIGkpKQo+ ICsKPiAgLyoqCj4gLSAqIGt2bV9hcm1faW5pdF9kZWJ1ZygpCj4gKyAqIGt2bV9hcm1faW5pdF9k ZWJ1ZygpIC0gY2hlY2sgZm9yIGd1ZXN0IGRlYnVnIGNhcGFiaWxpdGllcwo+ICAgKiBAY3M6IENQ VVN0YXRlCj4gICAqCj4gLSAqIENoZWNrIGZvciBndWVzdCBkZWJ1ZyBjYXBhYmlsaXRpZXMuCj4g KyAqIGt2bV9jaGVja19leHRlbnNpb24gcmV0dXJucyAwIGlmIHdlIGhhdmUgbm8gZGVidWcgcmVn aXN0ZXJzIG9yIHRoZQo+ICsgKiBudW1iZXIgd2UgaGF2ZS4KCnRoaXMgd291bGQgYmUgZWFzaWVy IHRvIHJlYWQgcGhyYXNlZCBhcyAia3ZtX2NoZWNrX2V4dGVuc2lvbiByZXR1cm5zCnRoZSBudW1i ZXIgb2YgZGVidWcgcmVnaXN0ZXJzIHdlIGhhdmUgKHdoaWNoIG1pZ2h0IGJlIG5vbmUpIi4KCj4g ICAqCj4gICAqLwo+ICBzdGF0aWMgdm9pZCBrdm1fYXJtX2luaXRfZGVidWcoQ1BVU3RhdGUgKmNz KQo+ICB7Cj4gICAgICBoYXZlX2d1ZXN0X2RlYnVnID0ga3ZtX2NoZWNrX2V4dGVuc2lvbihjcy0+ a3ZtX3N0YXRlLAo+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg S1ZNX0NBUF9TRVRfR1VFU1RfREVCVUcpOwo+ICsKPiArICAgIG1heF9od193cHMgPSBrdm1fY2hl Y2tfZXh0ZW5zaW9uKGNzLT5rdm1fc3RhdGUsIEtWTV9DQVBfR1VFU1RfREVCVUdfSFdfV1BTKTsK PiArICAgIGh3X3dhdGNocG9pbnRzID0gZ19hcnJheV9zaXplZF9uZXcodHJ1ZSwgdHJ1ZSwKPiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZW9mKEhXV2F0Y2hwb2lu dCksIG1heF9od193cHMpOwo+ICsKPiArICAgIG1heF9od19icHMgPSBrdm1fY2hlY2tfZXh0ZW5z aW9uKGNzLT5rdm1fc3RhdGUsIEtWTV9DQVBfR1VFU1RfREVCVUdfSFdfQlBTKTsKPiArICAgIGh3 X2JyZWFrcG9pbnRzID0gZ19hcnJheV9zaXplZF9uZXcodHJ1ZSwgdHJ1ZSwKPiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZW9mKEhXQnJlYWtwb2ludCksIG1heF9o d19icHMpOwo+ICAgICAgcmV0dXJuOwo+ICB9Cj4KPiArLyoqCj4gKyAqIGluc2VydF9od19icmVh a3BvaW50KCkKPiArICogQGFkZHI6IGFkZHJlc3Mgb2YgYnJlYWtwb2ludAo+ICsgKgo+ICsgKiBT ZWUgQVJNIEFSTSBEMi45LjEgZm9yIGRldGFpbHMgYnV0IGhlcmUgd2UgYXJlIG9ubHkgZ29pbmcg dG8gY3JlYXRlCj4gKyAqIHNpbXBsZSB1bi1saW5rZWQgYnJlYWtwb2ludHMgKGkuZS4gd2UgZG9u J3QgY2hhaW4gYnJlYWtwb2ludHMKPiArICogdG9nZXRoZXIgdG8gbWF0Y2ggYWRkcmVzcyBhbmQg Y29udGV4dCBvciB2bWlkKS4gVGhlIGhhcmR3YXJlIGlzCj4gKyAqIGNhcGFibGUgb2YgZmFuY2ll ciBtYXRjaGluZyBidXQgdGhhdCB3aWxsIHJlcXVpcmUgZXhwb3NpbmcgdGhhdAo+ICsgKiBmYW5j aW5lc3MgdG8gR0RCJ3MgaW50ZXJmYWNlCj4gKyAqCj4gKyAqIEQ3LjMuMiBEQkdCQ1I8bj5fRUwx LCBEZWJ1ZyBCcmVha3BvaW50IENvbnRyb2wgUmVnaXN0ZXJzCj4gKyAqCj4gKyAqICAzMSAgMjQg MjMgIDIwIDE5ICAgMTYgMTUgMTQgIDEzICAxMiAgIDkgOCAgIDUgNCAgICAzIDIgICAxICAwCj4g KyAqICstLS0tLS0rLS0tLS0tKy0tLS0tLS0rLS0tLS0rLS0tLSstLS0tLS0rLS0tLS0rLS0tLS0t Ky0tLS0tKy0tLSsKPiArICogfCBSRVMwIHwgIEJUICB8ICBMQk4gIHwgU1NDIHwgSE1DfCBSRVMw IHwgQkFTIHwgUkVTMCB8IFBNQyB8IEUgfAo+ICsgKiArLS0tLS0tKy0tLS0tLSstLS0tLS0tKy0t LS0tKy0tLS0rLS0tLS0tKy0tLS0tKy0tLS0tLSstLS0tLSstLS0rCj4gKyAqCj4gKyAqIEJUOiBC cmVha3BvaW50IHR5cGUgKDAgPSB1bmxpbmtlZCBhZGRyZXNzIG1hdGNoKQo+ICsgKiBMQk46IExp bmtlZCBCUCBudW1iZXIgKDAgPSB1bnVzZWQpCj4gKyAqIFNTQy9ITUMvUE1DOiBTZWN1cml0eSwg SGlnaGVyIGFuZCBQcml2IGFjY2VzcyBjb250cm9sIChUYWJsZSBELTEyKQo+ICsgKiBCQVM6IEJ5 dGUgQWRkcmVzcyBTZWxlY3QgKFJFUzEgZm9yIEFBcmNoNjQpCj4gKyAqIEU6IEVuYWJsZSBiaXQK PiArICovCj4gK3N0YXRpYyBpbnQgaW5zZXJ0X2h3X2JyZWFrcG9pbnQodGFyZ2V0X3Vsb25nIGFk ZHIpCj4gK3sKPiArICAgIEhXQnJlYWtwb2ludCBicmsgPSB7Cj4gKyAgICAgICAgLmJjciA9IDB4 MSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIEJDUiBFPTEsIGVuYWJsZSAqLwo+ICsg ICAgICAgIC5idnIgPSBhZGRyCj4gKyAgICB9Owo+ICsKPiArICAgIGlmIChjdXJfaHdfYnBzID49 IG1heF9od19icHMpIHsKPiArICAgICAgICByZXR1cm4gLUVOT0JVRlM7Cj4gKyAgICB9Cj4gKwo+ ICsgICAgYnJrLmJjciA9IGRlcG9zaXQzMihicmsuYmNyLCAxLCAyLCAweDMpOyAgIC8qIFBNQyA9 IDExICovCj4gKyAgICBicmsuYmNyID0gZGVwb3NpdDMyKGJyay5iY3IsIDUsIDQsIDB4Zik7ICAg LyogQkFTID0gUkVTMSAqLwo+ICsKPiArICAgIGdfYXJyYXlfYXBwZW5kX3ZhbChod19icmVha3Bv aW50cywgYnJrKTsKPiArCj4gKyAgICByZXR1cm4gMDsKPiArfQo+ICsKPiArLyoqCj4gKyAqIGRl bGV0ZV9od19icmVha3BvaW50KCkKPiArICogQHBjOiBhZGRyZXNzIG9mIGJyZWFrcG9pbnQKPiAr ICoKPiArICogRGVsZXRlIGEgYnJlYWtwb2ludCBhbmQgc2h1ZmZsZSBhbnkgYWJvdmUgZG93bgo+ ICsgKi8KPiArCj4gK3N0YXRpYyBpbnQgZGVsZXRlX2h3X2JyZWFrcG9pbnQodGFyZ2V0X3Vsb25n IHBjKQo+ICt7Cj4gKyAgICBpbnQgaTsKPiArICAgIGZvciAoaSA9IDA7IGkgPCBod19icmVha3Bv aW50cy0+bGVuOyBpKyspIHsKPiArICAgICAgICBIV0JyZWFrcG9pbnQgKmJyayA9IGdldF9od19i cChpKTsKPiArICAgICAgICBpZiAoYnJrLT5idnIgPT0gcGMpIHsKPiArICAgICAgICAgICAgZ19h cnJheV9yZW1vdmVfaW5kZXgoaHdfYnJlYWtwb2ludHMsIGkpOwo+ICsgICAgICAgICAgICByZXR1 cm4gMDsKPiArICAgICAgICB9Cj4gKyAgICB9Cj4gKyAgICByZXR1cm4gLUVOT0VOVDsKPiArfQo+ ICsKPiArLyoqCj4gKyAqIGluc2VydF9od193YXRjaHBvaW50KCkKPiArICogQGFkZHI6IGFkZHJl c3Mgb2Ygd2F0Y2ggcG9pbnQKPiArICogQGxlbjogc2l6ZSBvZiBhcmVhCj4gKyAqIEB0eXBlOiB0 eXBlIG9mIHdhdGNoIHBvaW50Cj4gKyAqCj4gKyAqIFNlZSBBUk0gQVJNIEQyLjEwLiBBcyB3aXRo IHRoZSBicmVha3BvaW50cyB3ZSBjYW4gZG8gc29tZSBhZHZhbmNlZAo+ICsgKiBzdHVmZiBpZiB3 ZSB3YW50IHRvLiBUaGUgd2F0Y2ggcG9pbnRzIGNhbiBiZSBsaW5rZWQgd2l0aCB0aGUgYnJlYWsK PiArICogcG9pbnRzIGFib3ZlIHRvIG1ha2UgdGhlbSBjb250ZXh0IGF3YXJlLiBIb3dldmVyIGZv ciBzaW1wbGljaXR5Cj4gKyAqIGN1cnJlbnRseSB3ZSBvbmx5IGRlYWwgd2l0aCBzaW1wbGUgcmVh ZC93cml0ZSB3YXRjaCBwb2ludHMuCj4gKyAqCj4gKyAqIEQ3LjMuMTEgREJHV0NSPG4+X0VMMSwg RGVidWcgV2F0Y2hwb2ludCBDb250cm9sIFJlZ2lzdGVycwo+ICsgKgo+ICsgKiAgMzEgIDI5IDI4 ICAgMjQgMjMgIDIxICAyMCAgMTkgMTYgMTUgMTQgIDEzICAgMTIgIDUgNCAgIDMgMiAgIDEgIDAK PiArICogKy0tLS0tLSstLS0tLS0tKy0tLS0tLSstLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0t Ky0tLS0tKy0tLS0tKy0tLSsKPiArICogfCBSRVMwIHwgIE1BU0sgfCBSRVMwIHwgV1QgfCBMQk4g fCBTU0MgfCBITUMgfCBCQVMgfCBMU0MgfCBQQUMgfCBFIHwKPiArICogKy0tLS0tLSstLS0tLS0t Ky0tLS0tLSstLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLSsKPiAr ICoKPiArICogTUFTSzogbnVtIGJpdHMgYWRkciBtYXNrICgwPW5vbmUsMDEvMTA9cmVzLDExPTMg Yml0cyAoOCBieXRlcykpCj4gKyAqIFdUOiAwIC0gdW5saW5rZWQsIDEgLSBsaW5rZWQgKG5vdCBj dXJyZW50bHkgdXNlZCkKPiArICogTEJOOiBMaW5rZWQgQlAgbnVtYmVyIChub3QgY3VycmVudGx5 IHVzZWQpCj4gKyAqIFNTQy9ITUMvUEFDOiBTZWN1cml0eSwgSGlnaGVyIGFuZCBQcml2IGFjY2Vz cyBjb250cm9sIChUYWJsZSBEMi0xMSkKPiArICogQkFTOiBCeXRlIEFkZHJlc3MgU2VsZWN0Cj4g KyAqIExTQzogTG9hZC9TdG9yZSBjb250cm9sICgwMTogbG9hZCwgMTA6IHN0b3JlLCAxMTogYm90 aCkKPiArICogRTogRW5hYmxlCj4gKyAqCj4gKyAqIFRoZSBib3R0b20gMiBiaXRzIG9mIHRoZSB2 YWx1ZSByZWdpc3RlciBhcmUgbWFza2VkLiBUaGVyZWZvcmUgdG8KPiArICogYnJlYWsgb24gYW55 IHNpemVzIHNtYWxsZXIgdGhhbiBhbiB1bmFsaWduZWQgd29yZCB5b3UgbmVlZCB0byBzZXQKPiAr ICogTUFTSz0wLCBCQVM9Yml0IHBlciBieXRlIGluIHF1ZXN0aW9uLiBGb3IgbGFyZ2VyIHJlZ2lv bnMgKF4yKSB5b3UKPiArICogbmVlZCB0byBlbnN1cmUgeW91IG1hc2sgdGhlIGFkZHJlc3MgYXMg cmVxdWlyZWQgYW5kIHNldCBCQVM9MHhmZgo+ICsgKi8KPiArCj4gK3N0YXRpYyBpbnQgaW5zZXJ0 X2h3X3dhdGNocG9pbnQodGFyZ2V0X3Vsb25nIGFkZHIsCj4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgdGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4gK3sKPiArICAgIEhXV2F0 Y2hwb2ludCB3cCA9IHsKPiArICAgICAgICAud2NyID0gMSwgLyogRT0xLCBlbmFibGUgKi8KPiAr ICAgICAgICAud3ZyID0gYWRkciAmICh+MHg3VUxMKSwKPiArICAgICAgICAuZGV0YWlscyA9IHsg LnZhZGRyID0gYWRkciwgLmxlbiA9IGxlbn0KClNob3VsZCBhdCBsZWFzdCBoYXZlIGEgc3BhY2Ug YWZ0ZXIgImxlbiIuCgo+ICsgICAgfTsKPiArCj4gKyAgICBpZiAoY3VyX2h3X3dwcyA+PSBtYXhf aHdfd3BzKSB7Cj4gKyAgICAgICAgcmV0dXJuIC1FTk9CVUZTOwo+ICsgICAgfQo+ICsKPiArICAg IC8qCj4gKyAgICAgKiBITUM9MCBTU0M9MCBQQUM9MyB3aWxsIGhpdCBFTDAgb3IgRUwxLCBhbnkg c2VjdXJpdHkgc3RhdGUsCj4gKyAgICAgKiB2YWxpZCB3aGV0aGVyIEVMMyBpcyBpbXBsZW1lbnRl ZCBvciBub3QKPiArICAgICAqLwo+ICsgICAgd3Aud2NyID0gZGVwb3NpdDMyKHdwLndjciwgMSwg MiwgMyk7Cj4gKwo+ICsgICAgc3dpdGNoICh0eXBlKSB7Cj4gKyAgICBjYXNlIEdEQl9XQVRDSFBP SU5UX1JFQUQ6Cj4gKyAgICAgICAgd3Aud2NyID0gZGVwb3NpdDMyKHdwLndjciwgMywgMiwgMSk7 Cj4gKyAgICAgICAgd3AuZGV0YWlscy5mbGFncyA9IEJQX01FTV9SRUFEOwo+ICsgICAgICAgIGJy ZWFrOwo+ICsgICAgY2FzZSBHREJfV0FUQ0hQT0lOVF9XUklURToKPiArICAgICAgICB3cC53Y3Ig PSBkZXBvc2l0MzIod3Aud2NyLCAzLCAyLCAyKTsKPiArICAgICAgICB3cC5kZXRhaWxzLmZsYWdz ID0gQlBfTUVNX1dSSVRFOwo+ICsgICAgICAgIGJyZWFrOwo+ICsgICAgY2FzZSBHREJfV0FUQ0hQ T0lOVF9BQ0NFU1M6Cj4gKyAgICAgICAgd3Aud2NyID0gZGVwb3NpdDMyKHdwLndjciwgMywgMiwg Myk7Cj4gKyAgICAgICAgd3AuZGV0YWlscy5mbGFncyA9IEJQX01FTV9BQ0NFU1M7Cj4gKyAgICAg ICAgYnJlYWs7Cj4gKyAgICBkZWZhdWx0Ogo+ICsgICAgICAgIGdfYXNzZXJ0X25vdF9yZWFjaGVk KCk7Cj4gKyAgICAgICAgYnJlYWs7Cj4gKyAgICB9Cj4gKyAgICBpZiAobGVuIDw9IDgpIHsKPiAr ICAgICAgICAvKiB3ZSBhbGlnbiB0aGUgYWRkcmVzcyBhbmQgc2V0IHRoZSBiaXRzIGluIEJBUyAq Lwo+ICsgICAgICAgIGludCBvZmYgPSBhZGRyICYgMHg3Owo+ICsgICAgICAgIGludCBiYXMgPSAo MSA8PCBsZW4pLTE7CgpNaXNzaW5nIHNwYWNlcyBhcm91bmQgb3BlcmF0b3IgIi0iIChoZXJlIGFu ZCBiZWxvdykuCgo+ICsKPiArICAgICAgICB3cC53Y3IgPSBkZXBvc2l0MzIod3Aud2NyLCA1ICsg b2ZmLCA4IC0gb2ZmLCBiYXMpOwo+ICsgICAgfSBlbHNlIHsKPiArICAgICAgICAvKiBGb3IgcmFu Z2VzIGFib3ZlIDggYnl0ZXMgd2UgbmVlZCB0byBiZSBhIHBvd2VyIG9mIDIgKi8KPiArICAgICAg ICBpZiAoaXNfcG93ZXJfb2ZfMihsZW4pKSB7Cj4gKyAgICAgICAgICAgIGludCBiaXRzID0gY3R6 NjQobGVuKTsKPiArCj4gKyAgICAgICAgICAgIHdwLnd2ciAmPSB+KCgxIDw8IGJpdHMpLTEpOwo+ ICsgICAgICAgICAgICB3cC53Y3IgPSBkZXBvc2l0MzIod3Aud2NyLCAyNCwgNCwgYml0cyk7Cj4g KyAgICAgICAgICAgIHdwLndjciA9IGRlcG9zaXQzMih3cC53Y3IsIDUsIDgsIDB4ZmYpOwo+ICsg ICAgICAgIH0gZWxzZSB7Cj4gKyAgICAgICAgICAgIHJldHVybiAtRU5PQlVGUzsKPiArICAgICAg ICB9Cj4gKyAgICB9Cj4gKwo+ICsgICAgZ19hcnJheV9hcHBlbmRfdmFsKGh3X3dhdGNocG9pbnRz LCB3cCk7Cj4gKyAgICByZXR1cm4gMDsKPiArfQo+ICsKPiArCj4gK3N0YXRpYyBib29sIGNoZWNr X3dhdGNocG9pbnRfaW5fcmFuZ2UoaW50IGksIHRhcmdldF91bG9uZyBhZGRyKQo+ICt7Cj4gKyAg ICBIV1dhdGNocG9pbnQgKndwID0gZ2V0X2h3X3dwKGkpOwo+ICsgICAgdWludDY0X3QgYWRkcl90 b3AsIGFkZHJfYm90dG9tID0gd3AtPnd2cjsKPiArICAgIGludCBiYXMgPSBleHRyYWN0MzIod3At PndjciwgNSwgOCk7Cj4gKyAgICBpbnQgbWFzayA9IGV4dHJhY3QzMih3cC0+d2NyLCAyNCwgNCk7 Cj4gKwo+ICsgICAgaWYgKG1hc2spIHsKPiArICAgICAgICBhZGRyX3RvcCA9IGFkZHJfYm90dG9t ICsgKDEgPDwgbWFzayk7Cj4gKyAgICB9IGVsc2Ugewo+ICsgICAgICAgIC8qIEJBUyBtdXN0IGJl IGNvbnRpZ3VvdXMgYnV0IGNhbiBvZmZzZXQgYWdhaW5zdCB0aGUgYmFzZQo+ICsgICAgICAgICAq IGFkZHJlc3MgaW4gREJHV1ZSICovCj4gKyAgICAgICAgYWRkcl9ib3R0b20gPSBhZGRyX2JvdHRv bSArIGN0ejMyKGJhcyk7Cj4gKyAgICAgICAgYWRkcl90b3AgPSBhZGRyX2JvdHRvbSArIGNsbzMy KGJhcyk7Cj4gKyAgICB9Cj4gKwo+ICsgICAgaWYgKGFkZHIgPj0gYWRkcl9ib3R0b20gJiYgYWRk ciA8PSBhZGRyX3RvcCkgewo+ICsgICAgICAgIHJldHVybiB0cnVlOwo+ICsgICAgfQo+ICsKPiAr ICAgIHJldHVybiBmYWxzZTsKPiArfQo+ICsKPiArLyoqCj4gKyAqIGRlbGV0ZV9od193YXRjaHBv aW50KCkKPiArICogQGFkZHI6IGFkZHJlc3Mgb2YgYnJlYWtwb2ludAo+ICsgKgo+ICsgKiBEZWxl dGUgYSBicmVha3BvaW50IGFuZCBzaHVmZmxlIGFueSBhYm92ZSBkb3duCj4gKyAqLwo+ICsKPiAr c3RhdGljIGludCBkZWxldGVfaHdfd2F0Y2hwb2ludCh0YXJnZXRfdWxvbmcgYWRkciwKPiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRfdWxvbmcgbGVuLCBpbnQgdHlwZSkK PiArewo+ICsgICAgaW50IGk7Cj4gKyAgICBmb3IgKGkgPSAwOyBpIDwgY3VyX2h3X3dwczsgaSsr KSB7Cj4gKyAgICAgICAgaWYgKGNoZWNrX3dhdGNocG9pbnRfaW5fcmFuZ2UoaSwgYWRkcikpIHsK PiArICAgICAgICAgICAgZ19hcnJheV9yZW1vdmVfaW5kZXgoaHdfd2F0Y2hwb2ludHMsIGkpOwo+ ICsgICAgICAgICAgICByZXR1cm4gMDsKPiArICAgICAgICB9Cj4gKyAgICB9Cj4gKyAgICByZXR1 cm4gLUVOT0VOVDsKPiArfQo+ICsKPiArCj4gK2ludCBrdm1fYXJjaF9pbnNlcnRfaHdfYnJlYWtw b2ludCh0YXJnZXRfdWxvbmcgYWRkciwKPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIHRhcmdldF91bG9uZyBsZW4sIGludCB0eXBlKQo+ICt7Cj4gKyAgICBzd2l0Y2ggKHR5cGUp IHsKPiArICAgIGNhc2UgR0RCX0JSRUFLUE9JTlRfSFc6Cj4gKyAgICAgICAgcmV0dXJuIGluc2Vy dF9od19icmVha3BvaW50KGFkZHIpOwo+ICsgICAgICAgIGJyZWFrOwo+ICsgICAgY2FzZSBHREJf V0FUQ0hQT0lOVF9SRUFEOgo+ICsgICAgY2FzZSBHREJfV0FUQ0hQT0lOVF9XUklURToKPiArICAg IGNhc2UgR0RCX1dBVENIUE9JTlRfQUNDRVNTOgo+ICsgICAgICAgIHJldHVybiBpbnNlcnRfaHdf d2F0Y2hwb2ludChhZGRyLCBsZW4sIHR5cGUpOwo+ICsgICAgZGVmYXVsdDoKPiArICAgICAgICBy ZXR1cm4gLUVOT1NZUzsKPiArICAgIH0KPiArfQo+ICsKPiAraW50IGt2bV9hcmNoX3JlbW92ZV9o d19icmVha3BvaW50KHRhcmdldF91bG9uZyBhZGRyLAo+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgdGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4gK3sKPiArICAgIHN3aXRj aCAodHlwZSkgewo+ICsgICAgY2FzZSBHREJfQlJFQUtQT0lOVF9IVzoKPiArICAgICAgICByZXR1 cm4gZGVsZXRlX2h3X2JyZWFrcG9pbnQoYWRkcik7Cj4gKyAgICAgICAgYnJlYWs7Cj4gKyAgICBj YXNlIEdEQl9XQVRDSFBPSU5UX1JFQUQ6Cj4gKyAgICBjYXNlIEdEQl9XQVRDSFBPSU5UX1dSSVRF Ogo+ICsgICAgY2FzZSBHREJfV0FUQ0hQT0lOVF9BQ0NFU1M6Cj4gKyAgICAgICAgcmV0dXJuIGRl bGV0ZV9od193YXRjaHBvaW50KGFkZHIsIGxlbiwgdHlwZSk7Cj4gKyAgICBkZWZhdWx0Ogo+ICsg ICAgICAgIHJldHVybiAtRU5PU1lTOwo+ICsgICAgfQo+ICt9Cj4gKwo+ICsKPiArdm9pZCBrdm1f YXJjaF9yZW1vdmVfYWxsX2h3X2JyZWFrcG9pbnRzKHZvaWQpCj4gK3sKPiArICAgIGlmIChjdXJf aHdfd3BzID4gMCkgewo+ICsgICAgICAgIGdfYXJyYXlfcmVtb3ZlX3JhbmdlKGh3X3dhdGNocG9p bnRzLCAwLCBjdXJfaHdfd3BzKTsKPiArICAgIH0KPiArICAgIGlmIChjdXJfaHdfYnBzID4gMCkg ewo+ICsgICAgICAgIGdfYXJyYXlfcmVtb3ZlX3JhbmdlKGh3X2JyZWFrcG9pbnRzLCAwLCBjdXJf aHdfYnBzKTsKPiArICAgIH0KPiArfQo+ICsKPiArdm9pZCBrdm1fYXJtX2NvcHlfaHdfZGVidWdf ZGF0YShzdHJ1Y3Qga3ZtX2d1ZXN0X2RlYnVnX2FyY2ggKnB0cikKPiArewo+ICsgICAgaW50IGk7 Cj4gKyAgICBtZW1zZXQocHRyLCAwLCBzaXplb2Yoc3RydWN0IGt2bV9ndWVzdF9kZWJ1Z19hcmNo KSk7Cj4gKwo+ICsgICAgZm9yIChpID0gMDsgaSA8IG1heF9od193cHM7IGkrKykgewo+ICsgICAg ICAgIEhXV2F0Y2hwb2ludCAqd3AgPSBnZXRfaHdfd3AoaSk7Cj4gKyAgICAgICAgcHRyLT5kYmdf d2NyW2ldID0gd3AtPndjcjsKPiArICAgICAgICBwdHItPmRiZ193dnJbaV0gPSB3cC0+d3ZyOwo+ ICsgICAgfQo+ICsgICAgZm9yIChpID0gMDsgaSA8IG1heF9od19icHM7IGkrKykgewo+ICsgICAg ICAgIEhXQnJlYWtwb2ludCAqYnAgPSBnZXRfaHdfYnAoaSk7Cj4gKyAgICAgICAgcHRyLT5kYmdf YmNyW2ldID0gYnAtPmJjcjsKPiArICAgICAgICBwdHItPmRiZ19idnJbaV0gPSBicC0+YnZyOwo+ ICsgICAgfQo+ICt9Cj4gKwo+ICtib29sIGt2bV9hcm1faHdfZGVidWdfYWN0aXZlKENQVVN0YXRl ICpjcykKPiArewo+ICsgICAgcmV0dXJuICgoY3VyX2h3X3dwcyA+IDApIHx8IChjdXJfaHdfYnBz ID4gMCkpID8gdHJ1ZSA6IGZhbHNlOwoKWW91IGRvbid0IG5lZGUgdGhlID86IGhlcmUuCgo+ICt9 Cj4gKwo+ICtib29sIGt2bV9hcm1fZmluZF9od19icmVha3BvaW50KENQVVN0YXRlICpjcHUsIHRh cmdldF91bG9uZyBwYykKPiArewo+ICsgICAgaWYgKGt2bV9hcm1faHdfZGVidWdfYWN0aXZlKGNw dSkpIHsKCkRvIHdlIG5lZWQgdG8gZG8gdGhpcyBjaGVjaz8gSSB0aGluayB0aGUgbG9vcCBjb25k aXRpb24Kd2lsbCBEVFJUIGlmIHRoZXJlIGFyZW4ndCBhbnkgY3VycmVudCBicmVha3BvaW50cy4K Cj4gKyAgICAgICAgaW50IGk7Cj4gKwo+ICsgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjdXJfaHdf YnBzOyBpKyspIHsKPiArICAgICAgICAgICAgSFdCcmVha3BvaW50ICpicCA9IGdldF9od19icChp KTsKPiArICAgICAgICAgICAgaWYgKGJwLT5idnIgPT0gcGMpIHsKPiArICAgICAgICAgICAgICAg IHJldHVybiB0cnVlOwo+ICsgICAgICAgICAgICB9Cj4gKyAgICAgICAgfQo+ICsgICAgfQo+ICsg ICAgcmV0dXJuIGZhbHNlOwo+ICt9Cj4gKwo+ICtDUFVXYXRjaHBvaW50ICprdm1fYXJtX2ZpbmRf aHdfd2F0Y2hwb2ludChDUFVTdGF0ZSAqY3B1LCB0YXJnZXRfdWxvbmcgYWRkcikKPiArewo+ICsg ICAgaWYgKGt2bV9hcm1faHdfZGVidWdfYWN0aXZlKGNwdSkpIHsKClNpbWlsYXJseSBoZXJlLgoK PiArICAgICAgICBpbnQgaTsKPiArCj4gKyAgICAgICAgZm9yIChpID0gMDsgaSA8IGN1cl9od193 cHM7IGkrKykgewo+ICsgICAgICAgICAgICBpZiAoY2hlY2tfd2F0Y2hwb2ludF9pbl9yYW5nZShp LCBhZGRyKSkgewo+ICsgICAgICAgICAgICAgICAgcmV0dXJuICZnZXRfaHdfd3AoaSktPmRldGFp bHM7Cj4gKyAgICAgICAgICAgIH0KPiArICAgICAgICB9Cj4gKyAgICB9Cj4gKyAgICByZXR1cm4g TlVMTDsKPiArfQo+ICsKPiArCj4gIHN0YXRpYyBpbmxpbmUgdm9pZCBzZXRfZmVhdHVyZSh1aW50 NjRfdCAqZmVhdHVyZXMsIGludCBmZWF0dXJlKQo+ICB7Cj4gICAgICAqZmVhdHVyZXMgfD0gMVVM TCA8PCBmZWF0dXJlOwo+IGRpZmYgLS1naXQgYS90YXJnZXQtYXJtL2t2bV9hcm0uaCBiL3Rhcmdl dC1hcm0va3ZtX2FybS5oCj4gaW5kZXggYjUxNjA0MS4uZGE4ODY1OCAxMDA2NDQKPiAtLS0gYS90 YXJnZXQtYXJtL2t2bV9hcm0uaAo+ICsrKyBiL3RhcmdldC1hcm0va3ZtX2FybS5oCj4gQEAgLTIx NSw0ICsyMTUsNDIgQEAgc3RhdGljIGlubGluZSBjb25zdCBjaGFyICpnaWNfY2xhc3NfbmFtZSh2 b2lkKQo+ICAgKi8KPiAgY29uc3QgY2hhciAqZ2ljdjNfY2xhc3NfbmFtZSh2b2lkKTsKPgo+ICsv KioKPiArICoga3ZtX2FybV9od19kZWJ1Z19hY3RpdmU6Cj4gKyAqCj4gKyAqIFJldHVybiBUUlVF IGlzIGFueSBoYXJkd2FyZSBicmVha3BvaW50cyBpbiB1c2UuCgoiaWYiLgoKPiArICovCj4gKwo+ ICtib29sIGt2bV9hcm1faHdfZGVidWdfYWN0aXZlKENQVVN0YXRlICpjcyk7Cj4gKwo+ICsvKioK PiArICoga3ZtX2FybV9jb3B5X2h3X2RlYnVnX2RhdGE6Cj4gKyAqCj4gKyAqIEBwdHI6IGt2bV9n dWVzdF9kZWJ1Z19hcmNoIHN0cnVjdHVyZQo+ICsgKgo+ICsgKiBDb3B5IHRoZSBhcmNoaXRlY3R1 cmUgc3BlY2lmaWMgZGVidWcgcmVnaXN0ZXJzIGludG8gdGhlCj4gKyAqIGt2bV9ndWVzdF9kZWJ1 ZyBpb2N0bCBzdHJ1Y3R1cmUuCj4gKyAqLwo+ICtzdHJ1Y3Qga3ZtX2d1ZXN0X2RlYnVnX2FyY2g7 Cj4gKwo+ICt2b2lkIGt2bV9hcm1fY29weV9od19kZWJ1Z19kYXRhKHN0cnVjdCBrdm1fZ3Vlc3Rf ZGVidWdfYXJjaCAqcHRyKTsKPiArCj4gKy8qKgo+ICsgKiBrdm1fYXJtX2ZpbmRfaHdfYnJlYWtw b2ludDoKPiArICogQGNwdTogQ1BVU3RhdGUKPiArICogQHBjOiBwYyBvZiBicmVha3BvaW50Cj4g KyAqCj4gKyAqIFJldHVybiBUUlVFIGlmIHRoZSBwYyBtYXRjaGVzIG9uZSBvZiBvdXIgYnJlYWtw b2ludHMuCj4gKyAqLwo+ICtib29sIGt2bV9hcm1fZmluZF9od19icmVha3BvaW50KENQVVN0YXRl ICpjcHUsIHRhcmdldF91bG9uZyBwYyk7Cj4gKwo+ICsvKioKPiArICoga3ZtX2FybV9maW5kX2h3 X3dhdGNocG9pbnQ6Cj4gKyAqIEBjcHU6IENQVVN0YXRlCj4gKyAqIEBhZGRyOiBhZGRyZXNzIG9m IHdhdGNocG9pbnQKPiArICoKPiArICogUmV0dXJuIHRoZSBDUFVXYXRjaHBvaW50IHN0cnVjdHVy ZSB0aGUgYWRkciBtYXRjaGVzIG9uZSBvZiBvdXIgd2F0Y2hwb2ludHMuCgpNaXNzaW5nICJpZiIg PyAob3IgbmVlZHMgcmVwaHJhc2luZykKCj4gKyAqLwo+ICtDUFVXYXRjaHBvaW50ICprdm1fYXJt X2ZpbmRfaHdfd2F0Y2hwb2ludChDUFVTdGF0ZSAqY3B1LCB0YXJnZXRfdWxvbmcgYWRkcik7Cj4g Kwo+ICAjZW5kaWYKPiAtLQo+IDIuNi4zCj4KCnRoYW5rcwotLSBQTU0KX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Ka3ZtYXJtIG1haWxpbmcgbGlzdAprdm1h cm1AbGlzdHMuY3MuY29sdW1iaWEuZWR1Cmh0dHBzOi8vbGlzdHMuY3MuY29sdW1iaWEuZWR1L21h aWxtYW4vbGlzdGluZm8va3ZtYXJtCg== From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49747) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zznve-0003Go-WD for qemu-devel@nongnu.org; Fri, 20 Nov 2015 10:48:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zznvc-0007DO-Jj for qemu-devel@nongnu.org; Fri, 20 Nov 2015 10:48:50 -0500 Received: from mail-vk0-x233.google.com ([2607:f8b0:400c:c05::233]:36618) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zznvc-0007D8-EY for qemu-devel@nongnu.org; Fri, 20 Nov 2015 10:48:48 -0500 Received: by vkay187 with SMTP id y187so8576vka.3 for ; Fri, 20 Nov 2015 07:48:47 -0800 (PST) MIME-Version: 1.0 In-Reply-To: <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> References: <1447345251-22625-1-git-send-email-alex.bennee@linaro.org> <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> From: Peter Maydell Date: Fri, 20 Nov 2015 15:48:28 +0000 Message-ID: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH v9 4/6] target-arm: kvm - add support for HW assisted debug List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: =?UTF-8?B?QWxleCBCZW5uw6ll?= Cc: kvm-devel , Marc Zyngier , QEMU Developers , qemu-arm@nongnu.org, Christoffer Dall , Zhichao Huang , Paolo Bonzini , "kvmarm@lists.cs.columbia.edu" , arm-mail-list On 12 November 2015 at 16:20, Alex Benn=C3=A9e wro= te: > This adds basic support for HW assisted debug. The ioctl interface to > KVM allows us to pass an implementation defined number of break and > watch point registers. When KVM_GUESTDBG_USE_HW is specified these > debug registers will be installed in place on the world switch into the > guest. > > The hardware is actually capable of more advanced matching but it is > unclear if this expressiveness is available via the gdbstub protocol. > > Signed-off-by: Alex Benn=C3=A9e > > --- > v2 > - correct setting of PMC/BAS/MASK > - improved commentary > - added helper function to check watchpoint in range > - fix find/deletion of watchpoints > v3 > - use internals.h definitions > v6 > - KVM_GUESTDBG_USE_HW_BP->KVM_GUESTDBG_USE_HW > - renamed some helper functions to avoid confusion > v9 > - fix merge conflicts on re-base > - rm asm/ptrace.h include > - add additional commentry for hw breakpoints > - explain gdb's model for HW bkpts > - fix up spacing, formatting as per checkpatch > - better PAC values > - use is_power_of_2 > - use _arm_ fn naming and add docs > - add a CPUWatchpoint structure for reporting > - replace manual array manipulation with g_array abstraction > --- > target-arm/kvm.c | 38 +++--- > target-arm/kvm64.c | 352 +++++++++++++++++++++++++++++++++++++++++++++= +++++- > target-arm/kvm_arm.h | 38 ++++++ > 3 files changed, 406 insertions(+), 22 deletions(-) > > diff --git a/target-arm/kvm.c b/target-arm/kvm.c > index d505a7e..1f57e92 100644 > --- a/target-arm/kvm.c > +++ b/target-arm/kvm.c > @@ -547,6 +547,20 @@ static int kvm_handle_debug(CPUState *cs, struct kvm= _run *run) > return true; > } > break; > + case EC_BREAKPOINT: > + if (kvm_arm_find_hw_breakpoint(cs, env->pc)) { > + return true; > + } > + break; > + case EC_WATCHPOINT: > + { > + CPUWatchpoint *wp =3D kvm_arm_find_hw_watchpoint(cs, arch_info->= far); This won't compile for 32-bit ARM. > + if (wp) { > + cs->watchpoint_hit =3D wp; > + return true; > + } > + break; > + } > default: > error_report("%s: unhandled debug exit (%"PRIx32", %"PRIx64")\n"= , > __func__, arch_info->hsr, env->pc); > @@ -608,6 +622,10 @@ void kvm_arch_update_guest_debug(CPUState *cs, struc= t kvm_guest_debug *dbg) > if (kvm_sw_breakpoints_active(cs)) { > dbg->control |=3D KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; > } > + if (kvm_arm_hw_debug_active(cs)) { > + dbg->control |=3D KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; > + kvm_arm_copy_hw_debug_data(&dbg->arch); > + } > } > > /* C6.6.29 BRK instruction */ > @@ -635,26 +653,6 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, stru= ct kvm_sw_breakpoint *bp) > return 0; > } > > -int kvm_arch_insert_hw_breakpoint(target_ulong addr, > - target_ulong len, int type) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > - return -EINVAL; > -} You've moved these functions into kvm64.c but haven't provided a stub version in kvm32.c... > - > -int kvm_arch_remove_hw_breakpoint(target_ulong addr, > - target_ulong len, int type) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > - return -EINVAL; > -} > - > - > -void kvm_arch_remove_all_hw_breakpoints(void) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > -} > - > void kvm_arch_init_irq_routing(KVMState *s) > { > } > diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c > index d087794..c468324 100644 > --- a/target-arm/kvm64.c > +++ b/target-arm/kvm64.c > @@ -2,6 +2,7 @@ > * ARM implementation of KVM hooks, 64 bit specific code > * > * Copyright Mian-M. Hamayun 2013, Virtual Open Systems > + * Copyright Alex Benn=C3=A9e 2014, Linaro > * > * This work is licensed under the terms of the GNU GPL, version 2 or la= ter. > * See the COPYING file in the top-level directory. > @@ -12,12 +13,17 @@ > #include > #include > #include > +#include > > +#include > #include > > #include "config-host.h" > #include "qemu-common.h" > #include "qemu/timer.h" > +#include "qemu/host-utils.h" > +#include "qemu/error-report.h" > +#include "exec/gdbstub.h" > #include "sysemu/sysemu.h" > #include "sysemu/kvm.h" > #include "kvm_arm.h" > @@ -27,20 +33,362 @@ > > static bool have_guest_debug; > > +/* > + * Although the ARM implementation of hardware assisted debugging > + * allows for different breakpoints per-core the current GDB interface Comma after "per-core". > + * treats them as a global pool of registers (which seems to be the > + * case for x86, ppc and s390). As a result we store one copy of > + * registers which is used for all active cores. > + * > + * Write access is serialised by virtue of the GDB protocol which > + * updates things. Read access (i.e. when the values are copied to the > + * vCPU) is also gated by GDBs run control. "GDB's". > + * > + * This is not unreasonable as most of the time debugging kernels you > + * never know which core will eventually execute your function. > + */ > + > +typedef struct { > + uint64_t bcr; > + uint64_t bvr; > +} HWBreakpoint; > + > +/* The watchpoint registers can cover more area than the requested > + * watchpoint so we need to store the additional information > + * somewhere. We also need to supply a CPUWatchpoint to the GDB stub > + * when the watchpoint is hit. > + */ > +typedef struct { > + uint64_t wcr; > + uint64_t wvr; > + CPUWatchpoint details; > +} HWWatchpoint; > + > +/* Maximum and current break/watch point counts */ > +int max_hw_bps, max_hw_wps; > +GArray *hw_breakpoints, *hw_watchpoints; > + > +#define cur_hw_wps (hw_watchpoints->len) > +#define cur_hw_bps (hw_breakpoints->len) > +#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i)= ) > +#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i)= ) > + > /** > - * kvm_arm_init_debug() > + * kvm_arm_init_debug() - check for guest debug capabilities > * @cs: CPUState > * > - * Check for guest debug capabilities. > + * kvm_check_extension returns 0 if we have no debug registers or the > + * number we have. this would be easier to read phrased as "kvm_check_extension returns the number of debug registers we have (which might be none)". > * > */ > static void kvm_arm_init_debug(CPUState *cs) > { > have_guest_debug =3D kvm_check_extension(cs->kvm_state, > KVM_CAP_SET_GUEST_DEBUG); > + > + max_hw_wps =3D kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBU= G_HW_WPS); > + hw_watchpoints =3D g_array_sized_new(true, true, > + sizeof(HWWatchpoint), max_hw_wps)= ; > + > + max_hw_bps =3D kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBU= G_HW_BPS); > + hw_breakpoints =3D g_array_sized_new(true, true, > + sizeof(HWBreakpoint), max_hw_bps)= ; > return; > } > > +/** > + * insert_hw_breakpoint() > + * @addr: address of breakpoint > + * > + * See ARM ARM D2.9.1 for details but here we are only going to create > + * simple un-linked breakpoints (i.e. we don't chain breakpoints > + * together to match address and context or vmid). The hardware is > + * capable of fancier matching but that will require exposing that > + * fanciness to GDB's interface > + * > + * D7.3.2 DBGBCR_EL1, Debug Breakpoint Control Registers > + * > + * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0 > + * +------+------+-------+-----+----+------+-----+------+-----+---+ > + * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E | > + * +------+------+-------+-----+----+------+-----+------+-----+---+ > + * > + * BT: Breakpoint type (0 =3D unlinked address match) > + * LBN: Linked BP number (0 =3D unused) > + * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12) > + * BAS: Byte Address Select (RES1 for AArch64) > + * E: Enable bit > + */ > +static int insert_hw_breakpoint(target_ulong addr) > +{ > + HWBreakpoint brk =3D { > + .bcr =3D 0x1, /* BCR E=3D1, enable *= / > + .bvr =3D addr > + }; > + > + if (cur_hw_bps >=3D max_hw_bps) { > + return -ENOBUFS; > + } > + > + brk.bcr =3D deposit32(brk.bcr, 1, 2, 0x3); /* PMC =3D 11 */ > + brk.bcr =3D deposit32(brk.bcr, 5, 4, 0xf); /* BAS =3D RES1 */ > + > + g_array_append_val(hw_breakpoints, brk); > + > + return 0; > +} > + > +/** > + * delete_hw_breakpoint() > + * @pc: address of breakpoint > + * > + * Delete a breakpoint and shuffle any above down > + */ > + > +static int delete_hw_breakpoint(target_ulong pc) > +{ > + int i; > + for (i =3D 0; i < hw_breakpoints->len; i++) { > + HWBreakpoint *brk =3D get_hw_bp(i); > + if (brk->bvr =3D=3D pc) { > + g_array_remove_index(hw_breakpoints, i); > + return 0; > + } > + } > + return -ENOENT; > +} > + > +/** > + * insert_hw_watchpoint() > + * @addr: address of watch point > + * @len: size of area > + * @type: type of watch point > + * > + * See ARM ARM D2.10. As with the breakpoints we can do some advanced > + * stuff if we want to. The watch points can be linked with the break > + * points above to make them context aware. However for simplicity > + * currently we only deal with simple read/write watch points. > + * > + * D7.3.11 DBGWCR_EL1, Debug Watchpoint Control Registers > + * > + * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0 > + * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ > + * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E | > + * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ > + * > + * MASK: num bits addr mask (0=3Dnone,01/10=3Dres,11=3D3 bits (8 bytes)) > + * WT: 0 - unlinked, 1 - linked (not currently used) > + * LBN: Linked BP number (not currently used) > + * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11) > + * BAS: Byte Address Select > + * LSC: Load/Store control (01: load, 10: store, 11: both) > + * E: Enable > + * > + * The bottom 2 bits of the value register are masked. Therefore to > + * break on any sizes smaller than an unaligned word you need to set > + * MASK=3D0, BAS=3Dbit per byte in question. For larger regions (^2) you > + * need to ensure you mask the address as required and set BAS=3D0xff > + */ > + > +static int insert_hw_watchpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + HWWatchpoint wp =3D { > + .wcr =3D 1, /* E=3D1, enable */ > + .wvr =3D addr & (~0x7ULL), > + .details =3D { .vaddr =3D addr, .len =3D len} Should at least have a space after "len". > + }; > + > + if (cur_hw_wps >=3D max_hw_wps) { > + return -ENOBUFS; > + } > + > + /* > + * HMC=3D0 SSC=3D0 PAC=3D3 will hit EL0 or EL1, any security state, > + * valid whether EL3 is implemented or not > + */ > + wp.wcr =3D deposit32(wp.wcr, 1, 2, 3); > + > + switch (type) { > + case GDB_WATCHPOINT_READ: > + wp.wcr =3D deposit32(wp.wcr, 3, 2, 1); > + wp.details.flags =3D BP_MEM_READ; > + break; > + case GDB_WATCHPOINT_WRITE: > + wp.wcr =3D deposit32(wp.wcr, 3, 2, 2); > + wp.details.flags =3D BP_MEM_WRITE; > + break; > + case GDB_WATCHPOINT_ACCESS: > + wp.wcr =3D deposit32(wp.wcr, 3, 2, 3); > + wp.details.flags =3D BP_MEM_ACCESS; > + break; > + default: > + g_assert_not_reached(); > + break; > + } > + if (len <=3D 8) { > + /* we align the address and set the bits in BAS */ > + int off =3D addr & 0x7; > + int bas =3D (1 << len)-1; Missing spaces around operator "-" (here and below). > + > + wp.wcr =3D deposit32(wp.wcr, 5 + off, 8 - off, bas); > + } else { > + /* For ranges above 8 bytes we need to be a power of 2 */ > + if (is_power_of_2(len)) { > + int bits =3D ctz64(len); > + > + wp.wvr &=3D ~((1 << bits)-1); > + wp.wcr =3D deposit32(wp.wcr, 24, 4, bits); > + wp.wcr =3D deposit32(wp.wcr, 5, 8, 0xff); > + } else { > + return -ENOBUFS; > + } > + } > + > + g_array_append_val(hw_watchpoints, wp); > + return 0; > +} > + > + > +static bool check_watchpoint_in_range(int i, target_ulong addr) > +{ > + HWWatchpoint *wp =3D get_hw_wp(i); > + uint64_t addr_top, addr_bottom =3D wp->wvr; > + int bas =3D extract32(wp->wcr, 5, 8); > + int mask =3D extract32(wp->wcr, 24, 4); > + > + if (mask) { > + addr_top =3D addr_bottom + (1 << mask); > + } else { > + /* BAS must be contiguous but can offset against the base > + * address in DBGWVR */ > + addr_bottom =3D addr_bottom + ctz32(bas); > + addr_top =3D addr_bottom + clo32(bas); > + } > + > + if (addr >=3D addr_bottom && addr <=3D addr_top) { > + return true; > + } > + > + return false; > +} > + > +/** > + * delete_hw_watchpoint() > + * @addr: address of breakpoint > + * > + * Delete a breakpoint and shuffle any above down > + */ > + > +static int delete_hw_watchpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + int i; > + for (i =3D 0; i < cur_hw_wps; i++) { > + if (check_watchpoint_in_range(i, addr)) { > + g_array_remove_index(hw_watchpoints, i); > + return 0; > + } > + } > + return -ENOENT; > +} > + > + > +int kvm_arch_insert_hw_breakpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + switch (type) { > + case GDB_BREAKPOINT_HW: > + return insert_hw_breakpoint(addr); > + break; > + case GDB_WATCHPOINT_READ: > + case GDB_WATCHPOINT_WRITE: > + case GDB_WATCHPOINT_ACCESS: > + return insert_hw_watchpoint(addr, len, type); > + default: > + return -ENOSYS; > + } > +} > + > +int kvm_arch_remove_hw_breakpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + switch (type) { > + case GDB_BREAKPOINT_HW: > + return delete_hw_breakpoint(addr); > + break; > + case GDB_WATCHPOINT_READ: > + case GDB_WATCHPOINT_WRITE: > + case GDB_WATCHPOINT_ACCESS: > + return delete_hw_watchpoint(addr, len, type); > + default: > + return -ENOSYS; > + } > +} > + > + > +void kvm_arch_remove_all_hw_breakpoints(void) > +{ > + if (cur_hw_wps > 0) { > + g_array_remove_range(hw_watchpoints, 0, cur_hw_wps); > + } > + if (cur_hw_bps > 0) { > + g_array_remove_range(hw_breakpoints, 0, cur_hw_bps); > + } > +} > + > +void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr) > +{ > + int i; > + memset(ptr, 0, sizeof(struct kvm_guest_debug_arch)); > + > + for (i =3D 0; i < max_hw_wps; i++) { > + HWWatchpoint *wp =3D get_hw_wp(i); > + ptr->dbg_wcr[i] =3D wp->wcr; > + ptr->dbg_wvr[i] =3D wp->wvr; > + } > + for (i =3D 0; i < max_hw_bps; i++) { > + HWBreakpoint *bp =3D get_hw_bp(i); > + ptr->dbg_bcr[i] =3D bp->bcr; > + ptr->dbg_bvr[i] =3D bp->bvr; > + } > +} > + > +bool kvm_arm_hw_debug_active(CPUState *cs) > +{ > + return ((cur_hw_wps > 0) || (cur_hw_bps > 0)) ? true : false; You don't nede the ?: here. > +} > + > +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc) > +{ > + if (kvm_arm_hw_debug_active(cpu)) { Do we need to do this check? I think the loop condition will DTRT if there aren't any current breakpoints. > + int i; > + > + for (i =3D 0; i < cur_hw_bps; i++) { > + HWBreakpoint *bp =3D get_hw_bp(i); > + if (bp->bvr =3D=3D pc) { > + return true; > + } > + } > + } > + return false; > +} > + > +CPUWatchpoint *kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong ad= dr) > +{ > + if (kvm_arm_hw_debug_active(cpu)) { Similarly here. > + int i; > + > + for (i =3D 0; i < cur_hw_wps; i++) { > + if (check_watchpoint_in_range(i, addr)) { > + return &get_hw_wp(i)->details; > + } > + } > + } > + return NULL; > +} > + > + > static inline void set_feature(uint64_t *features, int feature) > { > *features |=3D 1ULL << feature; > diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h > index b516041..da88658 100644 > --- a/target-arm/kvm_arm.h > +++ b/target-arm/kvm_arm.h > @@ -215,4 +215,42 @@ static inline const char *gic_class_name(void) > */ > const char *gicv3_class_name(void); > > +/** > + * kvm_arm_hw_debug_active: > + * > + * Return TRUE is any hardware breakpoints in use. "if". > + */ > + > +bool kvm_arm_hw_debug_active(CPUState *cs); > + > +/** > + * kvm_arm_copy_hw_debug_data: > + * > + * @ptr: kvm_guest_debug_arch structure > + * > + * Copy the architecture specific debug registers into the > + * kvm_guest_debug ioctl structure. > + */ > +struct kvm_guest_debug_arch; > + > +void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); > + > +/** > + * kvm_arm_find_hw_breakpoint: > + * @cpu: CPUState > + * @pc: pc of breakpoint > + * > + * Return TRUE if the pc matches one of our breakpoints. > + */ > +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc); > + > +/** > + * kvm_arm_find_hw_watchpoint: > + * @cpu: CPUState > + * @addr: address of watchpoint > + * > + * Return the CPUWatchpoint structure the addr matches one of our watchp= oints. Missing "if" ? (or needs rephrasing) > + */ > +CPUWatchpoint *kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong ad= dr); > + > #endif > -- > 2.6.3 > thanks -- PMM From mboxrd@z Thu Jan 1 00:00:00 1970 From: peter.maydell@linaro.org (Peter Maydell) Date: Fri, 20 Nov 2015 15:48:28 +0000 Subject: [PATCH v9 4/6] target-arm: kvm - add support for HW assisted debug In-Reply-To: <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> References: <1447345251-22625-1-git-send-email-alex.bennee@linaro.org> <1447345251-22625-5-git-send-email-alex.bennee@linaro.org> Message-ID: To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On 12 November 2015 at 16:20, Alex Benn?e wrote: > This adds basic support for HW assisted debug. The ioctl interface to > KVM allows us to pass an implementation defined number of break and > watch point registers. When KVM_GUESTDBG_USE_HW is specified these > debug registers will be installed in place on the world switch into the > guest. > > The hardware is actually capable of more advanced matching but it is > unclear if this expressiveness is available via the gdbstub protocol. > > Signed-off-by: Alex Benn?e > > --- > v2 > - correct setting of PMC/BAS/MASK > - improved commentary > - added helper function to check watchpoint in range > - fix find/deletion of watchpoints > v3 > - use internals.h definitions > v6 > - KVM_GUESTDBG_USE_HW_BP->KVM_GUESTDBG_USE_HW > - renamed some helper functions to avoid confusion > v9 > - fix merge conflicts on re-base > - rm asm/ptrace.h include > - add additional commentry for hw breakpoints > - explain gdb's model for HW bkpts > - fix up spacing, formatting as per checkpatch > - better PAC values > - use is_power_of_2 > - use _arm_ fn naming and add docs > - add a CPUWatchpoint structure for reporting > - replace manual array manipulation with g_array abstraction > --- > target-arm/kvm.c | 38 +++--- > target-arm/kvm64.c | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++- > target-arm/kvm_arm.h | 38 ++++++ > 3 files changed, 406 insertions(+), 22 deletions(-) > > diff --git a/target-arm/kvm.c b/target-arm/kvm.c > index d505a7e..1f57e92 100644 > --- a/target-arm/kvm.c > +++ b/target-arm/kvm.c > @@ -547,6 +547,20 @@ static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) > return true; > } > break; > + case EC_BREAKPOINT: > + if (kvm_arm_find_hw_breakpoint(cs, env->pc)) { > + return true; > + } > + break; > + case EC_WATCHPOINT: > + { > + CPUWatchpoint *wp = kvm_arm_find_hw_watchpoint(cs, arch_info->far); This won't compile for 32-bit ARM. > + if (wp) { > + cs->watchpoint_hit = wp; > + return true; > + } > + break; > + } > default: > error_report("%s: unhandled debug exit (%"PRIx32", %"PRIx64")\n", > __func__, arch_info->hsr, env->pc); > @@ -608,6 +622,10 @@ void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg) > if (kvm_sw_breakpoints_active(cs)) { > dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP; > } > + if (kvm_arm_hw_debug_active(cs)) { > + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW; > + kvm_arm_copy_hw_debug_data(&dbg->arch); > + } > } > > /* C6.6.29 BRK instruction */ > @@ -635,26 +653,6 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp) > return 0; > } > > -int kvm_arch_insert_hw_breakpoint(target_ulong addr, > - target_ulong len, int type) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > - return -EINVAL; > -} You've moved these functions into kvm64.c but haven't provided a stub version in kvm32.c... > - > -int kvm_arch_remove_hw_breakpoint(target_ulong addr, > - target_ulong len, int type) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > - return -EINVAL; > -} > - > - > -void kvm_arch_remove_all_hw_breakpoints(void) > -{ > - qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__); > -} > - > void kvm_arch_init_irq_routing(KVMState *s) > { > } > diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c > index d087794..c468324 100644 > --- a/target-arm/kvm64.c > +++ b/target-arm/kvm64.c > @@ -2,6 +2,7 @@ > * ARM implementation of KVM hooks, 64 bit specific code > * > * Copyright Mian-M. Hamayun 2013, Virtual Open Systems > + * Copyright Alex Benn?e 2014, Linaro > * > * This work is licensed under the terms of the GNU GPL, version 2 or later. > * See the COPYING file in the top-level directory. > @@ -12,12 +13,17 @@ > #include > #include > #include > +#include > > +#include > #include > > #include "config-host.h" > #include "qemu-common.h" > #include "qemu/timer.h" > +#include "qemu/host-utils.h" > +#include "qemu/error-report.h" > +#include "exec/gdbstub.h" > #include "sysemu/sysemu.h" > #include "sysemu/kvm.h" > #include "kvm_arm.h" > @@ -27,20 +33,362 @@ > > static bool have_guest_debug; > > +/* > + * Although the ARM implementation of hardware assisted debugging > + * allows for different breakpoints per-core the current GDB interface Comma after "per-core". > + * treats them as a global pool of registers (which seems to be the > + * case for x86, ppc and s390). As a result we store one copy of > + * registers which is used for all active cores. > + * > + * Write access is serialised by virtue of the GDB protocol which > + * updates things. Read access (i.e. when the values are copied to the > + * vCPU) is also gated by GDBs run control. "GDB's". > + * > + * This is not unreasonable as most of the time debugging kernels you > + * never know which core will eventually execute your function. > + */ > + > +typedef struct { > + uint64_t bcr; > + uint64_t bvr; > +} HWBreakpoint; > + > +/* The watchpoint registers can cover more area than the requested > + * watchpoint so we need to store the additional information > + * somewhere. We also need to supply a CPUWatchpoint to the GDB stub > + * when the watchpoint is hit. > + */ > +typedef struct { > + uint64_t wcr; > + uint64_t wvr; > + CPUWatchpoint details; > +} HWWatchpoint; > + > +/* Maximum and current break/watch point counts */ > +int max_hw_bps, max_hw_wps; > +GArray *hw_breakpoints, *hw_watchpoints; > + > +#define cur_hw_wps (hw_watchpoints->len) > +#define cur_hw_bps (hw_breakpoints->len) > +#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i)) > +#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i)) > + > /** > - * kvm_arm_init_debug() > + * kvm_arm_init_debug() - check for guest debug capabilities > * @cs: CPUState > * > - * Check for guest debug capabilities. > + * kvm_check_extension returns 0 if we have no debug registers or the > + * number we have. this would be easier to read phrased as "kvm_check_extension returns the number of debug registers we have (which might be none)". > * > */ > static void kvm_arm_init_debug(CPUState *cs) > { > have_guest_debug = kvm_check_extension(cs->kvm_state, > KVM_CAP_SET_GUEST_DEBUG); > + > + max_hw_wps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS); > + hw_watchpoints = g_array_sized_new(true, true, > + sizeof(HWWatchpoint), max_hw_wps); > + > + max_hw_bps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_BPS); > + hw_breakpoints = g_array_sized_new(true, true, > + sizeof(HWBreakpoint), max_hw_bps); > return; > } > > +/** > + * insert_hw_breakpoint() > + * @addr: address of breakpoint > + * > + * See ARM ARM D2.9.1 for details but here we are only going to create > + * simple un-linked breakpoints (i.e. we don't chain breakpoints > + * together to match address and context or vmid). The hardware is > + * capable of fancier matching but that will require exposing that > + * fanciness to GDB's interface > + * > + * D7.3.2 DBGBCR_EL1, Debug Breakpoint Control Registers > + * > + * 31 24 23 20 19 16 15 14 13 12 9 8 5 4 3 2 1 0 > + * +------+------+-------+-----+----+------+-----+------+-----+---+ > + * | RES0 | BT | LBN | SSC | HMC| RES0 | BAS | RES0 | PMC | E | > + * +------+------+-------+-----+----+------+-----+------+-----+---+ > + * > + * BT: Breakpoint type (0 = unlinked address match) > + * LBN: Linked BP number (0 = unused) > + * SSC/HMC/PMC: Security, Higher and Priv access control (Table D-12) > + * BAS: Byte Address Select (RES1 for AArch64) > + * E: Enable bit > + */ > +static int insert_hw_breakpoint(target_ulong addr) > +{ > + HWBreakpoint brk = { > + .bcr = 0x1, /* BCR E=1, enable */ > + .bvr = addr > + }; > + > + if (cur_hw_bps >= max_hw_bps) { > + return -ENOBUFS; > + } > + > + brk.bcr = deposit32(brk.bcr, 1, 2, 0x3); /* PMC = 11 */ > + brk.bcr = deposit32(brk.bcr, 5, 4, 0xf); /* BAS = RES1 */ > + > + g_array_append_val(hw_breakpoints, brk); > + > + return 0; > +} > + > +/** > + * delete_hw_breakpoint() > + * @pc: address of breakpoint > + * > + * Delete a breakpoint and shuffle any above down > + */ > + > +static int delete_hw_breakpoint(target_ulong pc) > +{ > + int i; > + for (i = 0; i < hw_breakpoints->len; i++) { > + HWBreakpoint *brk = get_hw_bp(i); > + if (brk->bvr == pc) { > + g_array_remove_index(hw_breakpoints, i); > + return 0; > + } > + } > + return -ENOENT; > +} > + > +/** > + * insert_hw_watchpoint() > + * @addr: address of watch point > + * @len: size of area > + * @type: type of watch point > + * > + * See ARM ARM D2.10. As with the breakpoints we can do some advanced > + * stuff if we want to. The watch points can be linked with the break > + * points above to make them context aware. However for simplicity > + * currently we only deal with simple read/write watch points. > + * > + * D7.3.11 DBGWCR_EL1, Debug Watchpoint Control Registers > + * > + * 31 29 28 24 23 21 20 19 16 15 14 13 12 5 4 3 2 1 0 > + * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ > + * | RES0 | MASK | RES0 | WT | LBN | SSC | HMC | BAS | LSC | PAC | E | > + * +------+-------+------+----+-----+-----+-----+-----+-----+-----+---+ > + * > + * MASK: num bits addr mask (0=none,01/10=res,11=3 bits (8 bytes)) > + * WT: 0 - unlinked, 1 - linked (not currently used) > + * LBN: Linked BP number (not currently used) > + * SSC/HMC/PAC: Security, Higher and Priv access control (Table D2-11) > + * BAS: Byte Address Select > + * LSC: Load/Store control (01: load, 10: store, 11: both) > + * E: Enable > + * > + * The bottom 2 bits of the value register are masked. Therefore to > + * break on any sizes smaller than an unaligned word you need to set > + * MASK=0, BAS=bit per byte in question. For larger regions (^2) you > + * need to ensure you mask the address as required and set BAS=0xff > + */ > + > +static int insert_hw_watchpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + HWWatchpoint wp = { > + .wcr = 1, /* E=1, enable */ > + .wvr = addr & (~0x7ULL), > + .details = { .vaddr = addr, .len = len} Should at least have a space after "len". > + }; > + > + if (cur_hw_wps >= max_hw_wps) { > + return -ENOBUFS; > + } > + > + /* > + * HMC=0 SSC=0 PAC=3 will hit EL0 or EL1, any security state, > + * valid whether EL3 is implemented or not > + */ > + wp.wcr = deposit32(wp.wcr, 1, 2, 3); > + > + switch (type) { > + case GDB_WATCHPOINT_READ: > + wp.wcr = deposit32(wp.wcr, 3, 2, 1); > + wp.details.flags = BP_MEM_READ; > + break; > + case GDB_WATCHPOINT_WRITE: > + wp.wcr = deposit32(wp.wcr, 3, 2, 2); > + wp.details.flags = BP_MEM_WRITE; > + break; > + case GDB_WATCHPOINT_ACCESS: > + wp.wcr = deposit32(wp.wcr, 3, 2, 3); > + wp.details.flags = BP_MEM_ACCESS; > + break; > + default: > + g_assert_not_reached(); > + break; > + } > + if (len <= 8) { > + /* we align the address and set the bits in BAS */ > + int off = addr & 0x7; > + int bas = (1 << len)-1; Missing spaces around operator "-" (here and below). > + > + wp.wcr = deposit32(wp.wcr, 5 + off, 8 - off, bas); > + } else { > + /* For ranges above 8 bytes we need to be a power of 2 */ > + if (is_power_of_2(len)) { > + int bits = ctz64(len); > + > + wp.wvr &= ~((1 << bits)-1); > + wp.wcr = deposit32(wp.wcr, 24, 4, bits); > + wp.wcr = deposit32(wp.wcr, 5, 8, 0xff); > + } else { > + return -ENOBUFS; > + } > + } > + > + g_array_append_val(hw_watchpoints, wp); > + return 0; > +} > + > + > +static bool check_watchpoint_in_range(int i, target_ulong addr) > +{ > + HWWatchpoint *wp = get_hw_wp(i); > + uint64_t addr_top, addr_bottom = wp->wvr; > + int bas = extract32(wp->wcr, 5, 8); > + int mask = extract32(wp->wcr, 24, 4); > + > + if (mask) { > + addr_top = addr_bottom + (1 << mask); > + } else { > + /* BAS must be contiguous but can offset against the base > + * address in DBGWVR */ > + addr_bottom = addr_bottom + ctz32(bas); > + addr_top = addr_bottom + clo32(bas); > + } > + > + if (addr >= addr_bottom && addr <= addr_top) { > + return true; > + } > + > + return false; > +} > + > +/** > + * delete_hw_watchpoint() > + * @addr: address of breakpoint > + * > + * Delete a breakpoint and shuffle any above down > + */ > + > +static int delete_hw_watchpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + int i; > + for (i = 0; i < cur_hw_wps; i++) { > + if (check_watchpoint_in_range(i, addr)) { > + g_array_remove_index(hw_watchpoints, i); > + return 0; > + } > + } > + return -ENOENT; > +} > + > + > +int kvm_arch_insert_hw_breakpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + switch (type) { > + case GDB_BREAKPOINT_HW: > + return insert_hw_breakpoint(addr); > + break; > + case GDB_WATCHPOINT_READ: > + case GDB_WATCHPOINT_WRITE: > + case GDB_WATCHPOINT_ACCESS: > + return insert_hw_watchpoint(addr, len, type); > + default: > + return -ENOSYS; > + } > +} > + > +int kvm_arch_remove_hw_breakpoint(target_ulong addr, > + target_ulong len, int type) > +{ > + switch (type) { > + case GDB_BREAKPOINT_HW: > + return delete_hw_breakpoint(addr); > + break; > + case GDB_WATCHPOINT_READ: > + case GDB_WATCHPOINT_WRITE: > + case GDB_WATCHPOINT_ACCESS: > + return delete_hw_watchpoint(addr, len, type); > + default: > + return -ENOSYS; > + } > +} > + > + > +void kvm_arch_remove_all_hw_breakpoints(void) > +{ > + if (cur_hw_wps > 0) { > + g_array_remove_range(hw_watchpoints, 0, cur_hw_wps); > + } > + if (cur_hw_bps > 0) { > + g_array_remove_range(hw_breakpoints, 0, cur_hw_bps); > + } > +} > + > +void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr) > +{ > + int i; > + memset(ptr, 0, sizeof(struct kvm_guest_debug_arch)); > + > + for (i = 0; i < max_hw_wps; i++) { > + HWWatchpoint *wp = get_hw_wp(i); > + ptr->dbg_wcr[i] = wp->wcr; > + ptr->dbg_wvr[i] = wp->wvr; > + } > + for (i = 0; i < max_hw_bps; i++) { > + HWBreakpoint *bp = get_hw_bp(i); > + ptr->dbg_bcr[i] = bp->bcr; > + ptr->dbg_bvr[i] = bp->bvr; > + } > +} > + > +bool kvm_arm_hw_debug_active(CPUState *cs) > +{ > + return ((cur_hw_wps > 0) || (cur_hw_bps > 0)) ? true : false; You don't nede the ?: here. > +} > + > +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc) > +{ > + if (kvm_arm_hw_debug_active(cpu)) { Do we need to do this check? I think the loop condition will DTRT if there aren't any current breakpoints. > + int i; > + > + for (i = 0; i < cur_hw_bps; i++) { > + HWBreakpoint *bp = get_hw_bp(i); > + if (bp->bvr == pc) { > + return true; > + } > + } > + } > + return false; > +} > + > +CPUWatchpoint *kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr) > +{ > + if (kvm_arm_hw_debug_active(cpu)) { Similarly here. > + int i; > + > + for (i = 0; i < cur_hw_wps; i++) { > + if (check_watchpoint_in_range(i, addr)) { > + return &get_hw_wp(i)->details; > + } > + } > + } > + return NULL; > +} > + > + > static inline void set_feature(uint64_t *features, int feature) > { > *features |= 1ULL << feature; > diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h > index b516041..da88658 100644 > --- a/target-arm/kvm_arm.h > +++ b/target-arm/kvm_arm.h > @@ -215,4 +215,42 @@ static inline const char *gic_class_name(void) > */ > const char *gicv3_class_name(void); > > +/** > + * kvm_arm_hw_debug_active: > + * > + * Return TRUE is any hardware breakpoints in use. "if". > + */ > + > +bool kvm_arm_hw_debug_active(CPUState *cs); > + > +/** > + * kvm_arm_copy_hw_debug_data: > + * > + * @ptr: kvm_guest_debug_arch structure > + * > + * Copy the architecture specific debug registers into the > + * kvm_guest_debug ioctl structure. > + */ > +struct kvm_guest_debug_arch; > + > +void kvm_arm_copy_hw_debug_data(struct kvm_guest_debug_arch *ptr); > + > +/** > + * kvm_arm_find_hw_breakpoint: > + * @cpu: CPUState > + * @pc: pc of breakpoint > + * > + * Return TRUE if the pc matches one of our breakpoints. > + */ > +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc); > + > +/** > + * kvm_arm_find_hw_watchpoint: > + * @cpu: CPUState > + * @addr: address of watchpoint > + * > + * Return the CPUWatchpoint structure the addr matches one of our watchpoints. Missing "if" ? (or needs rephrasing) > + */ > +CPUWatchpoint *kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr); > + > #endif > -- > 2.6.3 > thanks -- PMM