From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex =?utf-8?Q?Benn=C3=A9e?= Subject: Re: [PATCH v2 4/4] target-arm: kvm - add support for HW assisted debug Date: Tue, 21 Apr 2015 14:08:04 +0100 Message-ID: <87sibtvdcb.fsf@linaro.org> References: <1427816446-31586-1-git-send-email-alex.bennee@linaro.org> <1427816446-31586-5-git-send-email-alex.bennee@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from localhost (localhost [127.0.0.1]) by mm01.cs.columbia.edu (Postfix) with ESMTP id 1D9CD4D376 for ; Tue, 21 Apr 2015 08:59:34 -0400 (EDT) Received: from mm01.cs.columbia.edu ([127.0.0.1]) by localhost (mm01.cs.columbia.edu [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VjwDz9NNnG5M for ; Tue, 21 Apr 2015 08:59:32 -0400 (EDT) Received: from socrates.bennee.com (static.88-198-71-155.clients.your-server.de [88.198.71.155]) by mm01.cs.columbia.edu (Postfix) with ESMTPS id C64474D374 for ; Tue, 21 Apr 2015 08:59:31 -0400 (EDT) In-reply-to: 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 To: Peter Maydell Cc: kvm-devel , Marc Zyngier , QEMU Developers , Zhichao Huang , Paolo Bonzini , "kvmarm@lists.cs.columbia.edu" , arm-mail-list List-Id: kvmarm@lists.cs.columbia.edu ClBldGVyIE1heWRlbGwgPHBldGVyLm1heWRlbGxAbGluYXJvLm9yZz4gd3JpdGVzOgoKPiBPbiAz MSBNYXJjaCAyMDE1IGF0IDE2OjQwLCBBbGV4IEJlbm7DqWUgPGFsZXguYmVubmVlQGxpbmFyby5v cmc+IHdyb3RlOgo+PiBGcm9tOiBBbGV4IEJlbm7DqWUgPGFsZXhAYmVubmVlLmNvbT4KPj4KPj4g VGhpcyBhZGRzIGJhc2ljIHN1cHBvcnQgZm9yIEhXIGFzc2lzdGVkIGRlYnVnLiBUaGUgaW9jdGwg aW50ZXJmYWNlIHRvCj4+IEtWTSBhbGxvd3MgdXMgdG8gcGFzcyBhbiBpbXBsZW1lbnRhdGlvbiBk ZWZpbmVkIG51bWJlciBvZiBicmVhayBhbmQKPj4gd2F0Y2ggcG9pbnQgcmVnaXN0ZXJzLiBXaGVu IEtWTV9HVUVTVERCR19VU0VfSFdfQlAgaXMgc3BlY2lmaWVkIHRoZXNlCj4+IGRlYnVnIHJlZ2lz dGVycyB3aWxsIGJlIGluc3RhbGxlZCBpbiBwbGFjZSBvbiB0aGUgd29ybGQgc3dpdGNoIGludG8g dGhlCj4+IGd1ZXN0Lgo+Pgo+PiBUaGUgaGFyZHdhcmUgaXMgYWN0dWFsbHkgY2FwYWJsZSBvZiBt b3JlIGFkdmFuY2VkIG1hdGNoaW5nIGJ1dCBpdCBpcwo+PiB1bmNsZWFyIGlmIHRoaXMgZXhwcmVz c2l2ZW5lc3MgaXMgYXZhaWxhYmxlIHZpYSB0aGUgZ2Ric3R1YiBwcm90b2NvbC4KPj4KPj4gU2ln bmVkLW9mZi1ieTogQWxleCBCZW5uw6llIDxhbGV4LmJlbm5lZUBsaW5hcm8ub3JnPgo+Pgo+PiAt LS0KPj4gdjIKPj4gICAtIGNvcnJlY3Qgc2V0dGluZyBvZiBQTUMvQkFTL01BU0sKPj4gICAtIGlt cHJvdmVkIGNvbW1lbnRhcnkKPj4gICAtIGFkZGVkIGhlbHBlciBmdW5jdGlvbiB0byBjaGVjayB3 YXRjaHBvaW50IGluIHJhbmdlCj4+ICAgLSBmaXggZmluZC9kZWxldGlvbiBvZiB3YXRjaHBvaW50 cwo+Pgo+PiBkaWZmIC0tZ2l0IGEvdGFyZ2V0LWFybS9rdm0uYyBiL3RhcmdldC1hcm0va3ZtLmMK Pj4gaW5kZXggYWUwZjhiMi4uZDFhZGY1ZiAxMDA2NDQKPj4gLS0tIGEvdGFyZ2V0LWFybS9rdm0u Ywo+PiArKysgYi90YXJnZXQtYXJtL2t2bS5jCj4+IEBAIC0xNyw2ICsxNyw3IEBACj4+Cj4+ICAj aW5jbHVkZSAicWVtdS1jb21tb24uaCIKPj4gICNpbmNsdWRlICJxZW11L3RpbWVyLmgiCj4+ICsj aW5jbHVkZSAicWVtdS9lcnJvci1yZXBvcnQuaCIKPj4gICNpbmNsdWRlICJzeXNlbXUvc3lzZW11 LmgiCj4+ICAjaW5jbHVkZSAic3lzZW11L2t2bS5oIgo+PiAgI2luY2x1ZGUgImt2bV9hcm0uaCIK Pj4gQEAgLTQ3Niw2ICs0NzcsOCBAQCB2b2lkIGt2bV9hcmNoX3Bvc3RfcnVuKENQVVN0YXRlICpj cywgc3RydWN0IGt2bV9ydW4gKnJ1bikKPj4KPj4gICNkZWZpbmUgSFNSX0VDX1NISUZUICAgICAg ICAgICAgMjYKPj4gICNkZWZpbmUgSFNSX0VDX1NPRlRfU1RFUCAgICAgICAgMHgzMgo+PiArI2Rl ZmluZSBIU1JfRUNfSFdfQktQVCAgICAgICAgICAweDMwCj4+ICsjZGVmaW5lIEhTUl9FQ19IV19X QVRDSCAgICAgICAgIDB4MzQKPj4gICNkZWZpbmUgSFNSX0VDX1NXX0JLUFQgICAgICAgICAgMHgz Ywo+Pgo+PiAgc3RhdGljIGludCBrdm1faGFuZGxlX2RlYnVnKENQVVN0YXRlICpjcywgc3RydWN0 IGt2bV9ydW4gKnJ1bikKPj4gQEAgLTQ5Niw2ICs0OTksMTYgQEAgc3RhdGljIGludCBrdm1faGFu ZGxlX2RlYnVnKENQVVN0YXRlICpjcywgc3RydWN0IGt2bV9ydW4gKnJ1bikKPj4gICAgICAgICAg ICAgIHJldHVybiB0cnVlOwo+PiAgICAgICAgICB9Cj4+ICAgICAgICAgIGJyZWFrOwo+PiArICAg IGNhc2UgSFNSX0VDX0hXX0JLUFQ6Cj4+ICsgICAgICAgIGlmIChrdm1fYXJtX2ZpbmRfaHdfYnJl YWtwb2ludChjcywgYXJjaF9pbmZvLT5wYykpIHsKPj4gKyAgICAgICAgICAgIHJldHVybiB0cnVl Owo+PiArICAgICAgICB9Cj4+ICsgICAgICAgIGJyZWFrOwo+PiArICAgIGNhc2UgSFNSX0VDX0hX X1dBVENIOgo+PiArICAgICAgICBpZiAoa3ZtX2FybV9maW5kX2h3X3dhdGNocG9pbnQoY3MsIGFy Y2hfaW5mby0+ZmFyKSkgewo+PiArICAgICAgICAgICAgcmV0dXJuIHRydWU7Cj4+ICsgICAgICAg IH0KPj4gKyAgICAgICAgYnJlYWs7Cj4+ICAgICAgZGVmYXVsdDoKPj4gICAgICAgICAgZXJyb3Jf cmVwb3J0KCIlczogdW5oYW5kbGVkIGRlYnVnIGV4aXQgKCV4LCAlbGx4KVxuIiwKPj4gICAgICAg ICAgICAgICAgICAgICAgIF9fZnVuY19fLCBhcmNoX2luZm8tPmhzciwgYXJjaF9pbmZvLT5wYyk7 Cj4+IEBAIC01NTYsNiArNTY5LDEwIEBAIHZvaWQga3ZtX2FyY2hfdXBkYXRlX2d1ZXN0X2RlYnVn KENQVVN0YXRlICpjcywgc3RydWN0IGt2bV9ndWVzdF9kZWJ1ZyAqZGJnKQo+PiAgICAgIGlmIChr dm1fc3dfYnJlYWtwb2ludHNfYWN0aXZlKGNzKSkgewo+PiAgICAgICAgICBkYmctPmNvbnRyb2wg fD0gS1ZNX0dVRVNUREJHX0VOQUJMRSB8IEtWTV9HVUVTVERCR19VU0VfU1dfQlA7Cj4+ICAgICAg fQo+PiArICAgIGlmIChrdm1faHdfYnJlYWtwb2ludHNfYWN0aXZlKGNzKSkgewo+PiArICAgICAg ICBkYmctPmNvbnRyb2wgfD0gS1ZNX0dVRVNUREJHX0VOQUJMRSB8IEtWTV9HVUVTVERCR19VU0Vf SFdfQlA7Cj4+ICsgICAgICAgIGt2bV9jb3B5X2h3X2JyZWFrcG9pbnRfZGF0YSgmZGJnLT5hcmNo KTsKPj4gKyAgICB9Cj4+ICB9Cj4+Cj4+ICAvKiBDNi42LjI5IEJSSyBpbnN0cnVjdGlvbiAqLwo+ PiBAQCAtNTgyLDI2ICs1OTksNiBAQCBpbnQga3ZtX2FyY2hfcmVtb3ZlX3N3X2JyZWFrcG9pbnQo Q1BVU3RhdGUgKmNzLCBzdHJ1Y3Qga3ZtX3N3X2JyZWFrcG9pbnQgKmJwKQo+PiAgICAgIHJldHVy biAwOwo+PiAgfQo+Pgo+PiAtaW50IGt2bV9hcmNoX2luc2VydF9od19icmVha3BvaW50KHRhcmdl dF91bG9uZyBhZGRyLAo+PiAtICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdl dF91bG9uZyBsZW4sIGludCB0eXBlKQo+PiAtewo+PiAtICAgIHFlbXVfbG9nX21hc2soTE9HX1VO SU1QLCAiJXM6IG5vdCBpbXBsZW1lbnRlZFxuIiwgX19mdW5jX18pOwo+PiAtICAgIHJldHVybiAt RUlOVkFMOwo+PiAtfQo+PiAtCj4+IC1pbnQga3ZtX2FyY2hfcmVtb3ZlX2h3X2JyZWFrcG9pbnQo dGFyZ2V0X3Vsb25nIGFkZHIsCj4+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg dGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4+IC17Cj4+IC0gICAgcWVtdV9sb2dfbWFzayhM T0dfVU5JTVAsICIlczogbm90IGltcGxlbWVudGVkXG4iLCBfX2Z1bmNfXyk7Cj4+IC0gICAgcmV0 dXJuIC1FSU5WQUw7Cj4+IC19Cj4+IC0KPj4gLQo+PiAtdm9pZCBrdm1fYXJjaF9yZW1vdmVfYWxs X2h3X2JyZWFrcG9pbnRzKHZvaWQpCj4+IC17Cj4+IC0gICAgcWVtdV9sb2dfbWFzayhMT0dfVU5J TVAsICIlczogbm90IGltcGxlbWVudGVkXG4iLCBfX2Z1bmNfXyk7Cj4+IC19Cj4+IC0KPj4gIHZv aWQga3ZtX2FyY2hfaW5pdF9pcnFfcm91dGluZyhLVk1TdGF0ZSAqcykKPj4gIHsKPj4gIH0KPj4g ZGlmZiAtLWdpdCBhL3RhcmdldC1hcm0va3ZtNjQuYyBiL3RhcmdldC1hcm0va3ZtNjQuYwo+PiBp bmRleCA4Y2YzYTYyLi5kYmU4MWE3IDEwMDY0NAo+PiAtLS0gYS90YXJnZXQtYXJtL2t2bTY0LmMK Pj4gKysrIGIvdGFyZ2V0LWFybS9rdm02NC5jCj4+IEBAIC0yLDYgKzIsNyBAQAo+PiAgICogQVJN IGltcGxlbWVudGF0aW9uIG9mIEtWTSBob29rcywgNjQgYml0IHNwZWNpZmljIGNvZGUKPj4gICAq Cj4+ICAgKiBDb3B5cmlnaHQgTWlhbi1NLiBIYW1heXVuIDIwMTMsIFZpcnR1YWwgT3BlbiBTeXN0 ZW1zCj4+ICsgKiBDb3B5cmlnaHQgQWxleCBCZW5uw6llIDIwMTQsIExpbmFybwo+PiAgICoKPj4g ICAqIFRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHUEws IHZlcnNpb24gMiBvciBsYXRlci4KPj4gICAqIFNlZSB0aGUgQ09QWUlORyBmaWxlIGluIHRoZSB0 b3AtbGV2ZWwgZGlyZWN0b3J5Lgo+PiBAQCAtMTIsMTEgKzEzLDE3IEBACj4+ICAjaW5jbHVkZSA8 c3lzL3R5cGVzLmg+Cj4+ICAjaW5jbHVkZSA8c3lzL2lvY3RsLmg+Cj4+ICAjaW5jbHVkZSA8c3lz L21tYW4uaD4KPj4gKyNpbmNsdWRlIDxzeXMvcHRyYWNlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL3B0 cmFjZS5oPgo+Cj4gV2UgcmVhbGx5IG5lZWQgdGhlIGFzbS8gaW5jbHVkZSA/Cj4KPj4gKyNpbmNs dWRlIDxsaW51eC9lbGYuaD4KPj4gICNpbmNsdWRlIDxsaW51eC9rdm0uaD4KPj4KPj4gICNpbmNs dWRlICJxZW11LWNvbW1vbi5oIgo+PiAgI2luY2x1ZGUgInFlbXUvdGltZXIuaCIKPj4gKyNpbmNs dWRlICJxZW11L2hvc3QtdXRpbHMuaCIKPj4gKyNpbmNsdWRlICJxZW11L2Vycm9yLXJlcG9ydC5o Igo+PiArI2luY2x1ZGUgImV4ZWMvZ2Ric3R1Yi5oIgo+PiAgI2luY2x1ZGUgInN5c2VtdS9zeXNl bXUuaCIKPj4gICNpbmNsdWRlICJzeXNlbXUva3ZtLmgiCj4+ICAjaW5jbHVkZSAia3ZtX2FybS5o Igo+PiBAQCAtMjQsNiArMzEsMzEyIEBACj4+ICAjaW5jbHVkZSAiaW50ZXJuYWxzLmgiCj4+ICAj aW5jbHVkZSAiaHcvYXJtL2FybS5oIgo+Pgo+PiArLyogTWF4IGFuZCBjdXJyZW50IGJyZWFrL3dh dGNoIHBvaW50IGNvdW50cyAqLwo+PiAraW50IG1heF9od19icCwgbWF4X2h3X3dwOwo+PiAraW50 IGN1cl9od19icCwgY3VyX2h3X3dwOwo+PiArc3RydWN0IGt2bV9ndWVzdF9kZWJ1Z19hcmNoIGd1 ZXN0X2RlYnVnX3JlZ2lzdGVyczsKPgo+IEhvdyBkb2VzIHRoaXMgd29yayBpbiBhbiBTTVAgZ3Vl c3Q/CgpCYWRseSBJIGd1ZXNzIDstKQoKSW50ZXJlc3RpbmcgcHJvYmxlbSB0aG91Z2ggYmVjYXVz ZSBHREIgb25seSB0aGlua3MgaW4gdGVybXMgb2YgbgpicmVha3BvaW50cyByYXRoZXIgdGhhbiBh IHBlci1jcHUgcXVhbnRpdHkgc28gSSBndWVzcyB3ZSBqdXN0IGVuc3VyZSB3ZQpoYXZlIHRoZSBz YW1lIHNldCBvZiBkZWJ1ZyB2YWx1ZXMgYWNyb3NzIGFsbCB0aGUgdmNwdXM/Cgo+Cj4+ICsKPj4g Ky8qKgo+PiArICoga3ZtX2FybV9pbml0X2RlYnVnKCkKPj4gKyAqIEBjczogQ1BVU3RhdGUKPj4g KyAqCj4+ICsgKiBrdm1fY2hlY2tfZXh0ZW5zaW9uIHJldHVybnMgMCBpZiB3ZSBoYXZlIG5vIGRl YnVnIHJlZ2lzdGVycyBvciB0aGUKPj4gKyAqIG51bWJlciB3ZSBoYXZlLgo+PiArICoKPj4gKyAq Lwo+PiArc3RhdGljIHZvaWQga3ZtX2FybV9pbml0X2RlYnVnKENQVVN0YXRlICpjcykKPj4gK3sK Pj4gKyAgICBtYXhfaHdfd3AgPSBrdm1fY2hlY2tfZXh0ZW5zaW9uKGNzLT5rdm1fc3RhdGUsIEtW TV9DQVBfR1VFU1RfREVCVUdfSFdfV1BTKTsKPj4gKyAgICBtYXhfaHdfYnAgPSBrdm1fY2hlY2tf ZXh0ZW5zaW9uKGNzLT5rdm1fc3RhdGUsIEtWTV9DQVBfR1VFU1RfREVCVUdfSFdfQlBTKTsKPj4g KyAgICByZXR1cm47Cj4+ICt9Cj4+ICsKPj4gKy8qKgo+PiArICogaW5zZXJ0X2h3X2JyZWFrcG9p bnQoKQo+PiArICogQGFkZHI6IGFkZHJlc3Mgb2YgYnJlYWtwb2ludAo+PiArICoKPj4gKyAqIFNl ZSBBUk0gQVJNIEQyLjkuMSBmb3IgZGV0YWlscyBidXQgaGVyZSB3ZSBhcmUgb25seSBnb2luZyB0 byBjcmVhdGUKPj4gKyAqIHNpbXBsZSB1bi1saW5rZWQgYnJlYWtwb2ludHMgKGkuZS4gd2UgZG9u J3QgY2hhaW4gYnJlYWtwb2ludHMKPj4gKyAqIHRvZ2V0aGVyIHRvIG1hdGNoIGFkZHJlc3MgYW5k IGNvbnRleHQgb3Igdm1pZCkuIFRoZSBoYXJkd2FyZSBpcwo+PiArICogY2FwYWJsZSBvZiBmYW5j aWVyIG1hdGNoaW5nIGJ1dCB0aGF0IHdpbGwgcmVxdWlyZSBleHBvc2luZyB0aGF0Cj4+ICsgKiBm YW5jaW5lc3MgdG8gR0RCJ3MgaW50ZXJmYWNlCj4+ICsgKgo+PiArICogRDcuMy4yIERCR0JDUjxu Pl9FTDEsIERlYnVnIEJyZWFrcG9pbnQgQ29udHJvbCBSZWdpc3RlcnMKPj4gKyAqCj4+ICsgKiAg MzEgIDI0IDIzICAyMCAxOSAgIDE2IDE1IDE0ICAxMyAgMTIgICA5IDggICA1IDQgICAgMyAyICAg MSAgMAo+PiArICogKy0tLS0tLSstLS0tLS0rLS0tLS0tLSstLS0tLSstLS0tKy0tLS0tLSstLS0t LSstLS0tLS0rLS0tLS0rLS0tKwo+PiArICogfCBSRVMwIHwgIEJUICB8ICBMQk4gIHwgU1NDIHwg SE1DfCBSRVMwIHwgQkFTIHwgUkVTMCB8IFBNQyB8IEUgfAo+PiArICogKy0tLS0tLSstLS0tLS0r LS0tLS0tLSstLS0tLSstLS0tKy0tLS0tLSstLS0tLSstLS0tLS0rLS0tLS0rLS0tKwo+PiArICoK Pj4gKyAqIEJUOiBCcmVha3BvaW50IHR5cGUgKDAgPSB1bmxpbmtlZCBhZGRyZXNzIG1hdGNoKQo+ PiArICogTEJOOiBMaW5rZWQgQlAgbnVtYmVyICgwID0gdW51c2VkKQo+PiArICogU1NDL0hNQy9Q TUM6IFNlY3VyaXR5LCBIaWdoZXIgYW5kIFByaXYgYWNjZXNzIGNvbnRyb2wgKFRhYmxlIEQtMTIp Cj4+ICsgKiBCQVM6IEJ5dGUgQWRkcmVzcyBTZWxlY3QgKFJFUzEgZm9yIEFBcmNoNjQpCj4+ICsg KiBFOiBFbmFibGUgYml0Cj4+ICsgKi8KPj4gK3N0YXRpYyBpbnQgaW5zZXJ0X2h3X2JyZWFrcG9p bnQodGFyZ2V0X3Vsb25nIGFkZHIpCj4+ICt7Cj4+ICsgICAgdWludDMyX3QgYmNyID0gMHgxOyAv KiBFPTEsIGVuYWJsZSAqLwo+PiArICAgIGlmIChjdXJfaHdfYnAgPj0gbWF4X2h3X2JwKSB7Cj4+ ICsgICAgICAgIHJldHVybiAtRU5PQlVGUzsKPj4gKyAgICB9Cj4+ICsgICAgYmNyID0gZGVwb3Np dDMyKGJjciwgMSwgMiwgMHgzKTsgICAvKiBQTUMgPSAxMSAqLwo+PiArICAgIGJjciA9IGRlcG9z aXQzMihiY3IsIDUsIDQsIDB4Zik7ICAgLyogQkFTID0gUkVTMSAqLwo+PiArICAgIGd1ZXN0X2Rl YnVnX3JlZ2lzdGVycy5kYmdfYmNyW2N1cl9od19icF0gPSBiY3I7Cj4+ICsgICAgZ3Vlc3RfZGVi dWdfcmVnaXN0ZXJzLmRiZ19idnJbY3VyX2h3X2JwXSA9IGFkZHI7Cj4+ICsgICAgY3VyX2h3X2Jw Kys7Cj4+ICsgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gKy8qKgo+PiArICogZGVsZXRlX2h3 X2JyZWFrcG9pbnQoKQo+PiArICogQHBjOiBhZGRyZXNzIG9mIGJyZWFrcG9pbnQKPj4gKyAqCj4+ ICsgKiBEZWxldGUgYSBicmVha3BvaW50IGFuZCBzaHVmZmxlIGFueSBhYm92ZSBkb3duCj4+ICsg Ki8KPj4gKwo+PiArc3RhdGljIGludCBkZWxldGVfaHdfYnJlYWtwb2ludCh0YXJnZXRfdWxvbmcg cGMpCj4+ICt7Cj4+ICsgICAgaW50IGk7Cj4+ICsgICAgZm9yIChpID0gMDsgaSA8IGN1cl9od19i cDsgaSsrKSB7Cj4+ICsgICAgICBpZiAoZ3Vlc3RfZGVidWdfcmVnaXN0ZXJzLmRiZ19idnJbaV0g PT0gcGMpIHsKPj4gKyAgICAgICAgICB3aGlsZSAoaSA8IGN1cl9od19icCkgewo+PiArICAgICAg ICAgICAgICBpZiAoaSA9PSBtYXhfaHdfYnApIHsKPj4gKyAgICAgICAgICAgICAgICAgIGd1ZXN0 X2RlYnVnX3JlZ2lzdGVycy5kYmdfYnZyW2ldID0gMDsKPj4gKyAgICAgICAgICAgICAgICAgIGd1 ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfYmNyW2ldID0gMDsKPj4gKyAgICAgICAgICAgICAgfSBl bHNlIHsKPj4gKyAgICAgICAgICAgICAgICAgIGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfYnZy W2ldID0KPj4gKyAgICAgICAgICAgICAgICAgICAgICBndWVzdF9kZWJ1Z19yZWdpc3RlcnMuZGJn X2J2cltpICsgMV07Cj4+ICsgICAgICAgICAgICAgICAgICBndWVzdF9kZWJ1Z19yZWdpc3RlcnMu ZGJnX2JjcltpXSA9Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgZ3Vlc3RfZGVidWdfcmVnaXN0 ZXJzLmRiZ19iY3JbaSArIDFdOwo+Cj4gV2h5IGRvIHdlIG5lZWQgdG8gc2h1ZmZsZSBhbGwgdGhl IHJlZ2lzdGVycyBkb3duCj4gcmF0aGVyIHRoYW4ganVzdCBjbGVhcmluZyB0aGUgZW5hYmxlIGJp dCBvbiB0aGUgb25lCj4gd2Ugc3RvcHBlZCB1c2luZz8KCkl0IGtlZXBzIGl0IHNpbXBsZXIgd2hl biBjdXJfaHdfYnAgZXQgYWxsIGFyZSBib3RoIGEgY291bnQgYW5kIGFuIGluZGV4LgpUaGlzIGlz IGFsc28gc2F2ZXMgeW91IGZyb20gaGF2aW5nIHRvIHNodWZmbGUgdGhlbSBhcm91bmQgd2hlbiBw YWNraW5nCnRoZSAkSU1QREVGIGRlYnVnIHJlZ2lzdGVycyB0byB0aGUgc3RhcnQgb2YgdGhlIGFy cmF5LgoKPgo+PiArICAgICAgICAgICAgICB9Cj4+ICsgICAgICAgICAgICAgIGkrKzsKPj4gKyAg ICAgICAgICB9Cj4+ICsgICAgICAgICAgY3VyX2h3X2JwLS07Cj4+ICsgICAgICAgICAgcmV0dXJu IDA7Cj4+ICsgICAgICB9Cj4+ICsgICAgfQo+PiArICAgIHJldHVybiAtRU5PRU5UOwo+PiArfQo+ PiArCj4+ICsvKioKPj4gKyAqIGluc2VydF9od193YXRjaHBvaW50KCkKPj4gKyAqIEBhZGRyOiBh ZGRyZXNzIG9mIHdhdGNoIHBvaW50Cj4+ICsgKiBAbGVuOiBzaXplIG9mIGFyZWEKPj4gKyAqIEB0 eXBlOiB0eXBlIG9mIHdhdGNoIHBvaW50Cj4+ICsgKgo+PiArICogU2VlIEFSTSBBUk0gRDIuMTAu IEFzIHdpdGggdGhlIGJyZWFrcG9pbnRzIHdlIGNhbiBkbyBzb21lIGFkdmFuY2VkCj4+ICsgKiBz dHVmZiBpZiB3ZSB3YW50IHRvLiBUaGUgd2F0Y2ggcG9pbnRzIGNhbiBiZSBsaW5rZWQgd2l0aCB0 aGUgYnJlYWsKPj4gKyAqIHBvaW50cyBhYm92ZSB0byBtYWtlIHRoZW0gY29udGV4dCBhd2FyZS4g SG93ZXZlciBmb3Igc2ltcGxpY2l0eQo+PiArICogY3VycmVudGx5IHdlIG9ubHkgZGVhbCB3aXRo IHNpbXBsZSByZWFkL3dyaXRlIHdhdGNoIHBvaW50cy4KPj4gKyAqCj4+ICsgKiBENy4zLjExIERC R1dDUjxuPl9FTDEsIERlYnVnIFdhdGNocG9pbnQgQ29udHJvbCBSZWdpc3RlcnMKPj4gKyAqCj4+ ICsgKiAgMzEgIDI5IDI4ICAgMjQgMjMgIDIxICAyMCAgMTkgMTYgMTUgMTQgIDEzICAgMTIgIDUg NCAgIDMgMiAgIDEgIDAKPj4gKyAqICstLS0tLS0rLS0tLS0tLSstLS0tLS0rLS0tLSstLS0tLSst LS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0tLSstLS0rCj4+ICsgKiB8IFJFUzAgfCAgTUFTSyB8 IFJFUzAgfCBXVCB8IExCTiB8IFNTQyB8IEhNQyB8IEJBUyB8IExTQyB8IFBBQyB8IEUgfAo+PiAr ICogKy0tLS0tLSstLS0tLS0tKy0tLS0tLSstLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0tLS0tKy0t LS0tKy0tLS0tKy0tLSsKPj4gKyAqCj4+ICsgKiBNQVNLOiBudW0gYml0cyBhZGRyIG1hc2sgKDA9 bm9uZSwwMS8xMD1yZXMsMTE9MyBiaXRzICg4IGJ5dGVzKSkKPj4gKyAqIFdUOiAwIC0gdW5saW5r ZWQsIDEgLSBsaW5rZWQgKG5vdCBjdXJyZW50bHkgdXNlZCkKPj4gKyAqIExCTjogTGlua2VkIEJQ IG51bWJlciAobm90IGN1cnJlbnRseSB1c2VkKQo+PiArICogU1NDL0hNQy9QQUM6IFNlY3VyaXR5 LCBIaWdoZXIgYW5kIFByaXYgYWNjZXNzIGNvbnRyb2wgKFRhYmxlIEQtMTIpCj4+ICsgKiBCQVM6 IEJ5dGUgQWRkcmVzcyBTZWxlY3QKPj4gKyAqIExTQzogTG9hZC9TdG9yZSBjb250cm9sICgwMTog bG9hZCwgMTA6IHN0b3JlLCAxMTogYm90aCkKPj4gKyAqIEU6IEVuYWJsZQo+PiArICoKPj4gKyAq IFRoZSBib3R0b20gMiBiaXRzIG9mIHRoZSB2YWx1ZSByZWdpc3RlciBhcmUgbWFza2VkLiBUaGVy ZWZvciB0bwo+Cj4gIlRoZXJlZm9yZSIKPgo+PiArICogYnJlYWsgb24gYW4gc2l6ZXMgc21hbGxl ciB0aGFuIHVuYWxpZ25lZCBieXRlIHlvdSBuZWVkIHRvIHNldAo+Cj4gImFueSIuIEFsc28gd2hh dCdzIGEgc2l6ZSBzbWFsbGVyIHRoYW4gYW4gdW5hbGlnbmVkIGJ5dGU/IDotKQoKb29wcywgbm8g bmliYmxlIGJyZWFrIHBvaW50cyBJIGd1ZXNzIDstKQoKPgo+PiArICogTUFTSz0wLCBCQVM9Yml0 IHBlciBieXRlIGluIHF1ZXN0aW9uLiBGb3IgbGFyZ2VyIHJlZ2lvbnMgKF4yKSB5b3UKPj4gKyAq IG5lZWQgdG8gZW5zdXJlIHlvdSBtYXNrIHRoZSBhZGRyZXNzIGFzIHJlcXVpcmVkIGFuZCBzZXQg QkFTPTB4ZmYKPj4gKyAqLwo+PiArCj4+ICtzdGF0aWMgaW50IGluc2VydF9od193YXRjaHBvaW50 KHRhcmdldF91bG9uZyBhZGRyLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0 YXJnZXRfdWxvbmcgbGVuLCBpbnQgdHlwZSkKPj4gK3sKPj4gKyAgICB1aW50MzJfdCBkYmd3Y3Ig PSAxOyAvKiBFPTEsIGVuYWJsZSAqLwo+PiArICAgIHVpbnQ2NF90IGRiZ3d2ciA9IGFkZHIgJiAo fjB4N1VMTCk7Cj4+ICsKPj4gKyAgICBpZiAoY3VyX2h3X3dwID49IG1heF9od193cCkgewo+PiAr ICAgICAgICByZXR1cm4gLUVOT0JVRlM7Cj4+ICsgICAgfQo+PiArCj4+ICsgICAgLyogUEFDIDAw IGlzIHJlc2VydmVkLCBhc3N1bWUgRUwxIGV4Y2VwdGlvbiAqLwo+Cj4gTm90IHN1cmUgd2hhdCB0 aGlzIGNvbW1lbnQgaXMgdHJ5aW5nIHRvIHNheS4gUEFDIHZhbHVlIDAwIGlzCj4gcmVzZXJ2ZWQs IGJ1dCB5b3UncmUgbm90IHRyeWluZyB0byBzZXQgaXQgdG8gMDAgc28gdGhhdCdzIE9LLgo+Cj4+ ICsgICAgZGJnd2NyID0gZGVwb3NpdDMyKGRiZ3djciwgMSwgMiwgMSk7Cj4KPiBXaHkgYSBQQUMg dmFsdWUgb2YgMSA/IFRoYXQgbWVhbnMgd2Ugd2lsbCBvbmx5IGdldCB3YXRjaHBvaW50Cj4gaGl0 cyBmb3IgYWNjZXNzZXMgZnJvbSBFTDEsIHdoaWNoIGRvZXNuJ3QgcmVhbGx5IHNlZW0gbGlrZQo+ IHdoYXQgd2Ugd2FudC4gV2hhdCB5b3Ugd2FudCBJIHRoaW5rIGlzIEhNQz0wIFNTQz0wIFBBQz0z LAo+IHdoaWNoIHdpbGwgZ2l2ZSB5b3UgaGl0cyBmb3IgRUwwIG9yIEVMMSwgYW55IHNlY3VyaXR5 IHN0YXRlLAo+IHZhbGlkIHdoZXRoZXIgRUwzIGlzIGltcGxlbWVudGVkIG9yIG5vdC4KClRoYW5r cyAtIEkgZGlkbid0IGZpbmQgdGhlIHRhYmxlIGFzIGludHVpdGl2ZSBhcyBJIG1pZ2h0Li4uCgo+ Cj4KPj4gKwo+PiArICAgIHN3aXRjaCAodHlwZSkgewo+PiArICAgIGNhc2UgR0RCX1dBVENIUE9J TlRfUkVBRDoKPj4gKyAgICAgICAgZGJnd2NyID0gZGVwb3NpdDMyKGRiZ3djciwgMywgMiwgMSk7 Cj4+ICsgICAgICAgIGJyZWFrOwo+PiArICAgIGNhc2UgR0RCX1dBVENIUE9JTlRfV1JJVEU6Cj4+ ICsgICAgICAgIGRiZ3djciA9IGRlcG9zaXQzMihkYmd3Y3IsIDMsIDIsIDIpOwo+PiArICAgICAg ICBicmVhazsKPj4gKyAgICBjYXNlIEdEQl9XQVRDSFBPSU5UX0FDQ0VTUzoKPj4gKyAgICAgICAg ZGJnd2NyID0gZGVwb3NpdDMyKGRiZ3djciwgMywgMiwgMyk7Cj4+ICsgICAgICAgIGJyZWFrOwo+ PiArICAgIGRlZmF1bHQ6Cj4+ICsgICAgICAgIGdfYXNzZXJ0X25vdF9yZWFjaGVkKCk7Cj4+ICsg ICAgICAgIGJyZWFrOwo+PiArICAgIH0KPj4gKyAgICBpZiAobGVuIDw9IDgpIHsKPj4gKyAgICAg ICAgLyogd2UgYWxpZ24gdGhlIGFkZHJlc3MgYW5kIHNldCB0aGUgYml0cyBpbiBCQVMgKi8KPj4g KyAgICAgICAgaW50IG9mZiA9IGFkZHIgJiAweDc7Cj4+ICsgICAgICAgIGludCBiYXMgPSAoMSA8 PCBsZW4pLTE7Cj4KPgo+PiArICAgICAgICBkYmd3Y3IgPSBkZXBvc2l0MzIoZGJnd2NyLCA1K29m ZiwgOC1vZmYsIGJhcyk7Cj4KPiBNaXNzaW5nIHNwYWNlcy4KPgo+IEdpdmVuIHRoZSB3YXkgZGVw b3NpdDMyKCkgd29ya3MgeW91IGNvdWxkIGFsc28gc2F5Cj4gIGVuZCA9IE1JTihvZmYgKyBsZW4s IDgpOwo+ICBkYmd3Y3IgPSBkZXBvc2l0MzIoZGJnd2NyLCA1ICsgb2ZmLCA1ICsgZW5kLCB+MCk7 Cj4gd2hpY2ggaW52b2x2ZXMgYSBsaXR0bGUgbGVzcyBtYW51YWwgYml0LXR3aWRkbGluZy4KPgo+ IE5vdGUgdGhhdCBpZiB0aGUgdW5hbGlnbmVkIHdhdGNocG9pbnQgd2UncmUgdHJ5aW5nIHRvIHNl dAo+IHN0cmFkZGxlcyBhIGRvdWJsZXdvcmQgYm91bmRhcnkgKGVnIGEgNC1ieXRlIHdhdGNocG9p bnQgYXQKPiAweDEwMDYpIHdlJ2xsIG9ubHkgY2F0Y2ggYWNjZXNzZXMgdG8gdGhlIGZpcnN0IHBh cnQgb2YgaXQuCj4gVGhhdCBtYXkgYmUgT0ssIEkgZm9yZ2V0IHdoYXQgdGhlIGdkYnN0dWIncyBy ZXF1aXJlZAo+IHNlbWFudGljcyBmb3IgbGFyZ2VyLXRoYW4tYS1ieXRlIHdhdGNocG9pbnRzIGFy ZS4gSWYgbm90Cj4geW91J2xsIG5lZWQgdHdvIHdhdGNocG9pbnQgcmVncyB0byBjb3ZlciBib3Ro IHBhcnRzLgo+Cj4+ICsgICAgfSBlbHNlIHsKPj4gKyAgICAgICAgLyogRm9yIHJhbmdlcyBhYm92 ZSA4IGJ5dGVzIHdlIG5lZWQgdG8gYmUgYSBwb3dlciBvZiAyICovCj4+ICsgICAgICAgIGlmIChj dHBvcDY0KGxlbik9PTEpIHsKPgo+IElmIHlvdSB3YW50IHRvIHRlc3Qgd2hldGhlciBhIG51bWJl ciBpcyBhIHBvd2VyIG9mIDIgdGhlbgo+IHlvdSBjYW4gdXNlIGlzX3Bvd2VyX29mXzIoKS4uLgo+ Cj4+ICsgICAgICAgICAgICBpbnQgYml0cyA9IGN0ejY0KGxlbik7Cj4+ICsgICAgICAgICAgICBk Ymd3dnIgJj0gfigoMSA8PCBiaXRzKS0xKTsKPgo+IE1vcmUgc3BhY2luZyBpc3N1ZXMuCj4KPiAo Q2FuIHlvdSBhY3R1YWxseSBzZXQgYSBsYXJnZS1yYW5nZSB3YXRjaHBvaW50IHdpdGggZ2RiPykK CkknbGwgZG91YmxlIGNoZWNrLgoKPgo+PiArICAgICAgICAgICAgZGJnd2NyID0gZGVwb3NpdDMy KGRiZ3djciwgMjQsIDQsIGJpdHMpOwo+PiArICAgICAgICAgICAgZGJnd2NyID0gZGVwb3NpdDMy KGRiZ3djciwgNSwgOCwgMHhmZik7Cj4+ICsgICAgICAgIH0gZWxzZSB7Cj4+ICsgICAgICAgICAg ICByZXR1cm4gLUVOT0JVRlM7Cj4+ICsgICAgICAgIH0KPj4gKyAgICB9Cj4+ICsKPj4gKyAgICBn dWVzdF9kZWJ1Z19yZWdpc3RlcnMuZGJnX3djcltjdXJfaHdfd3BdID0gZGJnd2NyOwo+PiArICAg IGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfd3ZyW2N1cl9od193cF0gPSBkYmd3dnI7Cj4+ICsg ICAgY3VyX2h3X3dwKys7Cj4+ICsgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gKwo+PiArc3Rh dGljIGJvb2wgY2hlY2tfd2F0Y2hwb2ludF9pbl9yYW5nZShpbnQgaSwgdGFyZ2V0X3Vsb25nIGFk ZHIpCj4+ICt7Cj4+ICsgICAgdWludDMyX3QgZGJnd2NyID0gZ3Vlc3RfZGVidWdfcmVnaXN0ZXJz LmRiZ193Y3JbaV07Cj4+ICsgICAgdWludDY0X3QgYWRkcl90b3AsIGFkZHJfYm90dG9tID0gZ3Vl c3RfZGVidWdfcmVnaXN0ZXJzLmRiZ193dnJbaV07Cj4+ICsgICAgaW50IGJhcyA9IGV4dHJhY3Qz MihkYmd3Y3IsIDUsIDgpOwo+PiArICAgIGludCBtYXNrID0gZXh0cmFjdDMyKGRiZ3djciwgMjQs IDQpOwo+PiArCj4+ICsgICAgaWYgKG1hc2spIHsKPj4gKyAgICAgICAgYWRkcl90b3AgPSBhZGRy X2JvdHRvbSArICgxIDw8IG1hc2spOwo+PiArICAgIH0gZWxzZSB7Cj4+ICsgICAgICAgIC8qIEJB UyBtdXN0IGJlIGNvbnRpZ3VvdXMgYnV0IGNhbiBvZmZzZXQgYWdhaW5zdCB0aGUgYmFzZQo+PiAr ICAgICAgICAgKiBhZGRyZXNzIGluIERCR1dWUiAqLwo+PiArICAgICAgICBhZGRyX2JvdHRvbSA9 IGFkZHJfYm90dG9tICsgY3R6MzIoYmFzKTsKPj4gKyAgICAgICAgYWRkcl90b3AgPSBhZGRyX2Jv dHRvbSArIGNsbzMyKGJhcyk7Cj4+ICsgICAgfQo+PiArCj4+ICsgICAgaWYgKGFkZHIgPj0gYWRk cl9ib3R0b20gJiYgYWRkciA8PSBhZGRyX3RvcCApIHsKPj4gKyAgICAgICAgcmV0dXJuIHRydWU7 Cj4+ICsgICAgfQo+PiArCj4+ICsgICAgcmV0dXJuIGZhbHNlOwo+PiArfQo+PiArCj4+ICsvKioK Pj4gKyAqIGRlbGV0ZV9od193YXRjaHBvaW50KCkKPj4gKyAqIEBhZGRyOiBhZGRyZXNzIG9mIGJy ZWFrcG9pbnQKPj4gKyAqCj4+ICsgKiBEZWxldGUgYSBicmVha3BvaW50IGFuZCBzaHVmZmxlIGFu eSBhYm92ZSBkb3duCj4+ICsgKi8KPj4gKwo+PiArc3RhdGljIGludCBkZWxldGVfaHdfd2F0Y2hw b2ludCh0YXJnZXRfdWxvbmcgYWRkciwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgdGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4+ICt7Cj4+ICsgICAgaW50IGk7Cj4+ICsg ICAgZm9yIChpID0gMDsgaSA8IGN1cl9od193cDsgaSsrKSB7Cj4+ICsgICAgICAgIGlmIChjaGVj a193YXRjaHBvaW50X2luX3JhbmdlKGksIGFkZHIpKSB7Cj4+ICsgICAgICAgICAgICB3aGlsZSAo aSA8IGN1cl9od193cCkgewo+PiArICAgICAgICAgICAgICAgIGlmIChpID09IG1heF9od193cCkg ewo+PiArICAgICAgICAgICAgICAgICAgICBndWVzdF9kZWJ1Z19yZWdpc3RlcnMuZGJnX3d2cltp XSA9IDA7Cj4+ICsgICAgICAgICAgICAgICAgICAgIGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdf d2NyW2ldID0gMDsKPj4gKyAgICAgICAgICAgICAgICB9IGVsc2Ugewo+PiArICAgICAgICAgICAg ICAgICAgICBndWVzdF9kZWJ1Z19yZWdpc3RlcnMuZGJnX3d2cltpXSA9Cj4+ICsgICAgICAgICAg ICAgICAgICAgICAgICBndWVzdF9kZWJ1Z19yZWdpc3RlcnMuZGJnX3d2cltpICsgMV07Cj4+ICsg ICAgICAgICAgICAgICAgICAgIGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfd2NyW2ldID0KPj4g KyAgICAgICAgICAgICAgICAgICAgICAgIGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfd2NyW2kg KyAxXTsKPj4gKyAgICAgICAgICAgICAgICB9Cj4+ICsgICAgICAgICAgICAgICAgaSsrOwo+PiAr ICAgICAgICAgICAgfQo+PiArICAgICAgICAgICAgY3VyX2h3X3dwLS07Cj4+ICsgICAgICAgICAg ICByZXR1cm4gMDsKPj4gKyAgICAgICAgfQo+PiArICAgIH0KPj4gKyAgICByZXR1cm4gLUVOT0VO VDsKPj4gK30KPj4gKwo+PiArCj4+ICtpbnQga3ZtX2FyY2hfaW5zZXJ0X2h3X2JyZWFrcG9pbnQo dGFyZ2V0X3Vsb25nIGFkZHIsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg dGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4+ICt7Cj4+ICsgICAgc3dpdGNoICh0eXBlKSB7 Cj4+ICsgICAgY2FzZSBHREJfQlJFQUtQT0lOVF9IVzoKPj4gKyAgICAgICAgcmV0dXJuIGluc2Vy dF9od19icmVha3BvaW50KGFkZHIpOwo+PiArICAgICAgICBicmVhazsKPj4gKyAgICBjYXNlIEdE Ql9XQVRDSFBPSU5UX1JFQUQ6Cj4+ICsgICAgY2FzZSBHREJfV0FUQ0hQT0lOVF9XUklURToKPj4g KyAgICBjYXNlIEdEQl9XQVRDSFBPSU5UX0FDQ0VTUzoKPj4gKyAgICAgICAgcmV0dXJuIGluc2Vy dF9od193YXRjaHBvaW50KGFkZHIsIGxlbiwgdHlwZSk7Cj4+ICsgICAgZGVmYXVsdDoKPj4gKyAg ICAgICAgcmV0dXJuIC1FTk9TWVM7Cj4+ICsgICAgfQo+PiArfQo+PiArCj4+ICtpbnQga3ZtX2Fy Y2hfcmVtb3ZlX2h3X2JyZWFrcG9pbnQodGFyZ2V0X3Vsb25nIGFkZHIsCj4+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0X3Vsb25nIGxlbiwgaW50IHR5cGUpCj4+ICt7 Cj4+ICsgICAgc3dpdGNoICh0eXBlKSB7Cj4+ICsgICAgY2FzZSBHREJfQlJFQUtQT0lOVF9IVzoK Pj4gKyAgICAgICAgcmV0dXJuIGRlbGV0ZV9od19icmVha3BvaW50KGFkZHIpOwo+PiArICAgICAg ICBicmVhazsKPj4gKyAgICBjYXNlIEdEQl9XQVRDSFBPSU5UX1JFQUQ6Cj4+ICsgICAgY2FzZSBH REJfV0FUQ0hQT0lOVF9XUklURToKPj4gKyAgICBjYXNlIEdEQl9XQVRDSFBPSU5UX0FDQ0VTUzoK Pj4gKyAgICAgICAgcmV0dXJuIGRlbGV0ZV9od193YXRjaHBvaW50KGFkZHIsIGxlbiwgdHlwZSk7 Cj4+ICsgICAgZGVmYXVsdDoKPj4gKyAgICAgICAgcmV0dXJuIC1FTk9TWVM7Cj4+ICsgICAgfQo+ PiArfQo+PiArCj4+ICsKPj4gK3ZvaWQga3ZtX2FyY2hfcmVtb3ZlX2FsbF9od19icmVha3BvaW50 cyh2b2lkKQo+PiArewo+PiArICAgIG1lbXNldCgodm9pZCAqKSZndWVzdF9kZWJ1Z19yZWdpc3Rl cnMsIDAsIHNpemVvZihndWVzdF9kZWJ1Z19yZWdpc3RlcnMpKTsKPgo+IERvIHlvdSByZWFsbHkg bmVlZCB0aGlzIHZvaWQqIGNhc3Q/Cj4KPj4gKyAgICBjdXJfaHdfYnAgPSAwOwo+PiArICAgIGN1 cl9od193cCA9IDA7Cj4+ICt9Cj4+ICsKPj4gK3ZvaWQga3ZtX2NvcHlfaHdfYnJlYWtwb2ludF9k YXRhKHN0cnVjdCBrdm1fZ3Vlc3RfZGVidWdfYXJjaCAqcHRyKQo+PiArewo+PiArICAgIC8qIENv bXBpbGUgdGltZSBhc3NlcnQ/ICovCj4KPiBCZXR0ZXIgdGhhbiBydW50aW1lLCBidXQgd2h5IGFz c2VydCBhdCBhbGwsIGdpdmVuIHRoYXQgd2UndmUKPiBzaW1wbHkgZGVmaW5lZCBndWVzdF9kZWJ1 Z19yZWdpc3RlcnMgdG8gaGF2ZSB0aGUgcmlnaHQgdHlwZSBlYXJsaWVyCj4gYW5kIHRoZXJlJ3Mg bm90aGluZyBsaWtlbHkgdG8gbWFrZSB0aGF0IGdvIHN1YnRseSB3cm9uZz8KPgo+PiArICAgIGdf YXNzZXJ0KHNpemVvZihzdHJ1Y3Qga3ZtX2d1ZXN0X2RlYnVnX2FyY2gpID09IHNpemVvZihndWVz dF9kZWJ1Z19yZWdpc3RlcnMpKTsKPj4gKyAgICBtZW1jcHkocHRyLCAmZ3Vlc3RfZGVidWdfcmVn aXN0ZXJzLCBzaXplb2YoZ3Vlc3RfZGVidWdfcmVnaXN0ZXJzKSk7Cj4+ICt9Cj4+ICsKPj4gK2Jv b2wga3ZtX2h3X2JyZWFrcG9pbnRzX2FjdGl2ZShDUFVTdGF0ZSAqY3MpCj4+ICt7Cj4+ICsgICAg cmV0dXJuICggKGN1cl9od19icCA+IDApIHx8IChjdXJfaHdfd3AgPjApICkgPyBUUlVFOkZBTFNF Owo+Cj4gWW91J3ZlIGJlZW4gcmVhZGluZyB0b28gbXVjaCBzb2Z0ZmxvYXQgY29kZSwgdGhpcyBz cGFjaW5nCj4gc3R5bGUgaXMgYXRyb2Npb3VzIDotKSBBbHNvLCB0cnVlLCBub3QgVFJVRS4KCkkn bSBnb2luZyB0byBoYXZlIHRvIGludmVzdGlnYXRlIEVtYWNzJyBzdHlsZSBzZXR0aW5ncyB0byBz ZWUgaWYgSSBjYW4KZ2V0IHRoZSBzcGFjaW5nIGF1dG9tYXRpY2FsbHkuLi4KCj4KPj4gK30KPj4g Kwo+PiArYm9vbCBrdm1fYXJtX2ZpbmRfaHdfYnJlYWtwb2ludChDUFVTdGF0ZSAqY3B1LCB0YXJn ZXRfdWxvbmcgcGMpCj4+ICt7Cj4+ICsgIGlmIChrdm1faHdfYnJlYWtwb2ludHNfYWN0aXZlKGNw dSkpIHsKPj4gKyAgICBpbnQgaTsKPj4gKyAgICBmb3IgKGk9MDsgaTxjdXJfaHdfYnA7IGkrKykg ewo+PiArICAgICAgaWYgKGd1ZXN0X2RlYnVnX3JlZ2lzdGVycy5kYmdfYnZyW2ldID09IHBjKSB7 Cj4+ICsgICAgICAgIHJldHVybiB0cnVlOwo+PiArICAgICAgfQo+PiArICAgIH0KPj4gKyAgfQo+ PiArICByZXR1cm4gZmFsc2U7Cj4+ICt9Cj4+ICsKPj4gK2Jvb2wga3ZtX2FybV9maW5kX2h3X3dh dGNocG9pbnQoQ1BVU3RhdGUgKmNwdSwgdGFyZ2V0X3Vsb25nIGFkZHIpCj4+ICt7Cj4+ICsgIGlm IChrdm1faHdfYnJlYWtwb2ludHNfYWN0aXZlKGNwdSkpIHsKPj4gKyAgICBpbnQgaTsKPj4gKyAg ICBmb3IgKGk9MDsgaTxjdXJfaHdfd3A7IGkrKykgewo+Cj4gU3BhY2VzIQo+Cj4+ICsgICAgICAg IGlmIChjaGVja193YXRjaHBvaW50X2luX3JhbmdlKGksIGFkZHIpKSB7Cj4+ICsgICAgICAgICAg ICAgICAgcmV0dXJuIHRydWU7Cj4+ICsgICAgICAgIH0KPj4gKyAgICB9Cj4+ICsgIH0KPj4gKyAg cmV0dXJuIGZhbHNlOwo+PiArfQo+PiArCj4+ICsKPj4gIHN0YXRpYyBpbmxpbmUgdm9pZCBzZXRf ZmVhdHVyZSh1aW50NjRfdCAqZmVhdHVyZXMsIGludCBmZWF0dXJlKQo+PiAgewo+PiAgICAgICpm ZWF0dXJlcyB8PSAxVUxMIDw8IGZlYXR1cmU7Cj4+IEBAIC0xMDYsNiArNDE5LDggQEAgaW50IGt2 bV9hcmNoX2luaXRfdmNwdShDUFVTdGF0ZSAqY3MpCj4+ICAgICAgICAgIHJldHVybiByZXQ7Cj4+ ICAgICAgfQo+Pgo+PiArICAgIGt2bV9hcm1faW5pdF9kZWJ1Zyhjcyk7Cj4+ICsKPj4gICAgICBy ZXR1cm4ga3ZtX2FybV9pbml0X2NwcmVnX2xpc3QoY3B1KTsKPj4gIH0KPj4KPj4gZGlmZiAtLWdp dCBhL3RhcmdldC1hcm0va3ZtX2FybS5oIGIvdGFyZ2V0LWFybS9rdm1fYXJtLmgKPj4gaW5kZXgg NDU1ZGVhMy4uYTRiNDgwYiAxMDA2NDQKPj4gLS0tIGEvdGFyZ2V0LWFybS9rdm1fYXJtLmgKPj4g KysrIGIvdGFyZ2V0LWFybS9rdm1fYXJtLmgKPj4gQEAgLTE2Miw2ICsxNjIsMjcgQEAgdHlwZWRl ZiBzdHJ1Y3QgQVJNSG9zdENQVUNsYXNzIHsKPj4gICAqLwo+PiAgYm9vbCBrdm1fYXJtX2dldF9o b3N0X2NwdV9mZWF0dXJlcyhBUk1Ib3N0Q1BVQ2xhc3MgKmFoY2MpOwo+Pgo+PiArYm9vbCBrdm1f aHdfYnJlYWtwb2ludHNfYWN0aXZlKENQVVN0YXRlICpjcyk7Cj4+ICt2b2lkIGt2bV9jb3B5X2h3 X2JyZWFrcG9pbnRfZGF0YShzdHJ1Y3Qga3ZtX2d1ZXN0X2RlYnVnX2FyY2ggKnB0cik7Cj4KPiBJ ZiB0aGVzZSBhcmVuJ3QgY29tbW9uLXRvLWFsbC1DUFVzIGZ1bmN0aW9ucyB0aGV5IHNob3VsZAo+ IGhhdmUgYW4gX2FybV8gaW4gdGhlaXIgbmFtZXMuIChPdGhlcndpc2UgeW91J2QgZXhwZWN0Cj4g dG8gZmluZCBrdm1faHdfYnJlYWtwb2ludHNfYWN0aXZlKCkgbmV4dCB0bwo+IGt2bV9zd19icmVh a3BvaW50c19hY3RpdmUoKSBpbiBrdm0tYWxsLmMuKQoKT0sgdGhhbmtzCgo+Cj4gQWxzbywgZG9j IGNvbW1lbnRzIGZvciB0aGUgZnVuY3Rpb25zIHdvdWxkIGJlIG5pY2UuCj4KPj4gKwo+PiArLyoq Cj4+ICsgKiBrdm1fYXJtX2ZpbmRfaHdfYnJlYWtwb2ludDoKPj4gKyAqIEBjcHU6IENQVVN0YXRl Cj4+ICsgKiBAcGM6IHBjIG9mIGJyZWFrcG9pbnQKPj4gKyAqCj4+ICsgKiBSZXR1cm4gVFJVRSBp ZiB0aGUgcGMgbWF0Y2hlcyBvbmUgb2Ygb3VyIGJyZWFrcG9pbnRzLgo+PiArICovCj4+ICtib29s IGt2bV9hcm1fZmluZF9od19icmVha3BvaW50KENQVVN0YXRlICpjcHUsIHRhcmdldF91bG9uZyBw Yyk7Cj4+ICsKPj4gKy8qKgo+PiArICoga3ZtX2FybV9maW5kX2h3X3dhdGNocG9pbnQ6Cj4+ICsg KiBAY3B1OiBDUFVTdGF0ZQo+PiArICogQGFkZHI6IGFkZHJlc3Mgb2Ygd2F0Y2hwb2ludAo+PiAr ICoKPj4gKyAqIFJldHVybiBUUlVFIGlmIHRoZSBhZGRyIG1hdGNoZXMgb25lIG9mIG91ciB3YXRj aHBvaW50cy4KPj4gKyAqLwo+PiArYm9vbCBrdm1fYXJtX2ZpbmRfaHdfd2F0Y2hwb2ludChDUFVT dGF0ZSAqY3B1LCB0YXJnZXRfdWxvbmcgYWRkcik7Cj4+ICsKPj4gICNlbmRpZgo+Pgo+PiAgI2Vu ZGlmCj4KPiB0aGFua3MKPiAtLSBQTU0KCi0tIApBbGV4IEJlbm7DqWUKX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18Ka3ZtYXJtIG1haWxpbmcgbGlzdAprdm1h cm1AbGlzdHMuY3MuY29sdW1iaWEuZWR1Cmh0dHBzOi8vbGlzdHMuY3MuY29sdW1iaWEuZWR1L21h aWxtYW4vbGlzdGluZm8va3ZtYXJtCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: alex.bennee@linaro.org (Alex =?utf-8?Q?Benn=C3=A9e?=) Date: Tue, 21 Apr 2015 14:08:04 +0100 Subject: [PATCH v2 4/4] target-arm: kvm - add support for HW assisted debug In-Reply-To: References: <1427816446-31586-1-git-send-email-alex.bennee@linaro.org> <1427816446-31586-5-git-send-email-alex.bennee@linaro.org> Message-ID: <87sibtvdcb.fsf@linaro.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Peter Maydell writes: > On 31 March 2015 at 16:40, Alex Benn?e wrote: >> From: Alex Benn?e >> >> 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_BP 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 >> >> diff --git a/target-arm/kvm.c b/target-arm/kvm.c >> index ae0f8b2..d1adf5f 100644 >> --- a/target-arm/kvm.c >> +++ b/target-arm/kvm.c >> @@ -17,6 +17,7 @@ >> >> #include "qemu-common.h" >> #include "qemu/timer.h" >> +#include "qemu/error-report.h" >> #include "sysemu/sysemu.h" >> #include "sysemu/kvm.h" >> #include "kvm_arm.h" >> @@ -476,6 +477,8 @@ void kvm_arch_post_run(CPUState *cs, struct kvm_run *run) >> >> #define HSR_EC_SHIFT 26 >> #define HSR_EC_SOFT_STEP 0x32 >> +#define HSR_EC_HW_BKPT 0x30 >> +#define HSR_EC_HW_WATCH 0x34 >> #define HSR_EC_SW_BKPT 0x3c >> >> static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) >> @@ -496,6 +499,16 @@ static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) >> return true; >> } >> break; >> + case HSR_EC_HW_BKPT: >> + if (kvm_arm_find_hw_breakpoint(cs, arch_info->pc)) { >> + return true; >> + } >> + break; >> + case HSR_EC_HW_WATCH: >> + if (kvm_arm_find_hw_watchpoint(cs, arch_info->far)) { >> + return true; >> + } >> + break; >> default: >> error_report("%s: unhandled debug exit (%x, %llx)\n", >> __func__, arch_info->hsr, arch_info->pc); >> @@ -556,6 +569,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_hw_breakpoints_active(cs)) { >> + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; >> + kvm_copy_hw_breakpoint_data(&dbg->arch); >> + } >> } >> >> /* C6.6.29 BRK instruction */ >> @@ -582,26 +599,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; >> -} >> - >> -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 8cf3a62..dbe81a7 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,11 +13,17 @@ >> #include >> #include >> #include >> +#include >> +#include > > We really need the asm/ include ? > >> +#include >> #include >> >> #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" >> @@ -24,6 +31,312 @@ >> #include "internals.h" >> #include "hw/arm/arm.h" >> >> +/* Max and current break/watch point counts */ >> +int max_hw_bp, max_hw_wp; >> +int cur_hw_bp, cur_hw_wp; >> +struct kvm_guest_debug_arch guest_debug_registers; > > How does this work in an SMP guest? Badly I guess ;-) Interesting problem though because GDB only thinks in terms of n breakpoints rather than a per-cpu quantity so I guess we just ensure we have the same set of debug values across all the vcpus? > >> + >> +/** >> + * kvm_arm_init_debug() >> + * @cs: CPUState >> + * >> + * kvm_check_extension returns 0 if we have no debug registers or the >> + * number we have. >> + * >> + */ >> +static void kvm_arm_init_debug(CPUState *cs) >> +{ >> + max_hw_wp = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS); >> + max_hw_bp = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_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) >> +{ >> + uint32_t bcr = 0x1; /* E=1, enable */ >> + if (cur_hw_bp >= max_hw_bp) { >> + return -ENOBUFS; >> + } >> + bcr = deposit32(bcr, 1, 2, 0x3); /* PMC = 11 */ >> + bcr = deposit32(bcr, 5, 4, 0xf); /* BAS = RES1 */ >> + guest_debug_registers.dbg_bcr[cur_hw_bp] = bcr; >> + guest_debug_registers.dbg_bvr[cur_hw_bp] = addr; >> + cur_hw_bp++; >> + 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 < cur_hw_bp; i++) { >> + if (guest_debug_registers.dbg_bvr[i] == pc) { >> + while (i < cur_hw_bp) { >> + if (i == max_hw_bp) { >> + guest_debug_registers.dbg_bvr[i] = 0; >> + guest_debug_registers.dbg_bcr[i] = 0; >> + } else { >> + guest_debug_registers.dbg_bvr[i] = >> + guest_debug_registers.dbg_bvr[i + 1]; >> + guest_debug_registers.dbg_bcr[i] = >> + guest_debug_registers.dbg_bcr[i + 1]; > > Why do we need to shuffle all the registers down > rather than just clearing the enable bit on the one > we stopped using? It keeps it simpler when cur_hw_bp et all are both a count and an index. This is also saves you from having to shuffle them around when packing the $IMPDEF debug registers to the start of the array. > >> + } >> + i++; >> + } >> + cur_hw_bp--; >> + 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 D-12) >> + * 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. Therefor to > > "Therefore" > >> + * break on an sizes smaller than unaligned byte you need to set > > "any". Also what's a size smaller than an unaligned byte? :-) oops, no nibble break points I guess ;-) > >> + * 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) >> +{ >> + uint32_t dbgwcr = 1; /* E=1, enable */ >> + uint64_t dbgwvr = addr & (~0x7ULL); >> + >> + if (cur_hw_wp >= max_hw_wp) { >> + return -ENOBUFS; >> + } >> + >> + /* PAC 00 is reserved, assume EL1 exception */ > > Not sure what this comment is trying to say. PAC value 00 is > reserved, but you're not trying to set it to 00 so that's OK. > >> + dbgwcr = deposit32(dbgwcr, 1, 2, 1); > > Why a PAC value of 1 ? That means we will only get watchpoint > hits for accesses from EL1, which doesn't really seem like > what we want. What you want I think is HMC=0 SSC=0 PAC=3, > which will give you hits for EL0 or EL1, any security state, > valid whether EL3 is implemented or not. Thanks - I didn't find the table as intuitive as I might... > > >> + >> + switch (type) { >> + case GDB_WATCHPOINT_READ: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 1); >> + break; >> + case GDB_WATCHPOINT_WRITE: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 2); >> + break; >> + case GDB_WATCHPOINT_ACCESS: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 3); >> + 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; > > >> + dbgwcr = deposit32(dbgwcr, 5+off, 8-off, bas); > > Missing spaces. > > Given the way deposit32() works you could also say > end = MIN(off + len, 8); > dbgwcr = deposit32(dbgwcr, 5 + off, 5 + end, ~0); > which involves a little less manual bit-twiddling. > > Note that if the unaligned watchpoint we're trying to set > straddles a doubleword boundary (eg a 4-byte watchpoint at > 0x1006) we'll only catch accesses to the first part of it. > That may be OK, I forget what the gdbstub's required > semantics for larger-than-a-byte watchpoints are. If not > you'll need two watchpoint regs to cover both parts. > >> + } else { >> + /* For ranges above 8 bytes we need to be a power of 2 */ >> + if (ctpop64(len)==1) { > > If you want to test whether a number is a power of 2 then > you can use is_power_of_2()... > >> + int bits = ctz64(len); >> + dbgwvr &= ~((1 << bits)-1); > > More spacing issues. > > (Can you actually set a large-range watchpoint with gdb?) I'll double check. > >> + dbgwcr = deposit32(dbgwcr, 24, 4, bits); >> + dbgwcr = deposit32(dbgwcr, 5, 8, 0xff); >> + } else { >> + return -ENOBUFS; >> + } >> + } >> + >> + guest_debug_registers.dbg_wcr[cur_hw_wp] = dbgwcr; >> + guest_debug_registers.dbg_wvr[cur_hw_wp] = dbgwvr; >> + cur_hw_wp++; >> + return 0; >> +} >> + >> + >> +static bool check_watchpoint_in_range(int i, target_ulong addr) >> +{ >> + uint32_t dbgwcr = guest_debug_registers.dbg_wcr[i]; >> + uint64_t addr_top, addr_bottom = guest_debug_registers.dbg_wvr[i]; >> + int bas = extract32(dbgwcr, 5, 8); >> + int mask = extract32(dbgwcr, 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_wp; i++) { >> + if (check_watchpoint_in_range(i, addr)) { >> + while (i < cur_hw_wp) { >> + if (i == max_hw_wp) { >> + guest_debug_registers.dbg_wvr[i] = 0; >> + guest_debug_registers.dbg_wcr[i] = 0; >> + } else { >> + guest_debug_registers.dbg_wvr[i] = >> + guest_debug_registers.dbg_wvr[i + 1]; >> + guest_debug_registers.dbg_wcr[i] = >> + guest_debug_registers.dbg_wcr[i + 1]; >> + } >> + i++; >> + } >> + cur_hw_wp--; >> + 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) >> +{ >> + memset((void *)&guest_debug_registers, 0, sizeof(guest_debug_registers)); > > Do you really need this void* cast? > >> + cur_hw_bp = 0; >> + cur_hw_wp = 0; >> +} >> + >> +void kvm_copy_hw_breakpoint_data(struct kvm_guest_debug_arch *ptr) >> +{ >> + /* Compile time assert? */ > > Better than runtime, but why assert at all, given that we've > simply defined guest_debug_registers to have the right type earlier > and there's nothing likely to make that go subtly wrong? > >> + g_assert(sizeof(struct kvm_guest_debug_arch) == sizeof(guest_debug_registers)); >> + memcpy(ptr, &guest_debug_registers, sizeof(guest_debug_registers)); >> +} >> + >> +bool kvm_hw_breakpoints_active(CPUState *cs) >> +{ >> + return ( (cur_hw_bp > 0) || (cur_hw_wp >0) ) ? TRUE:FALSE; > > You've been reading too much softfloat code, this spacing > style is atrocious :-) Also, true, not TRUE. I'm going to have to investigate Emacs' style settings to see if I can get the spacing automatically... > >> +} >> + >> +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc) >> +{ >> + if (kvm_hw_breakpoints_active(cpu)) { >> + int i; >> + for (i=0; i> + if (guest_debug_registers.dbg_bvr[i] == pc) { >> + return true; >> + } >> + } >> + } >> + return false; >> +} >> + >> +bool kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr) >> +{ >> + if (kvm_hw_breakpoints_active(cpu)) { >> + int i; >> + for (i=0; i > Spaces! > >> + if (check_watchpoint_in_range(i, addr)) { >> + return true; >> + } >> + } >> + } >> + return false; >> +} >> + >> + >> static inline void set_feature(uint64_t *features, int feature) >> { >> *features |= 1ULL << feature; >> @@ -106,6 +419,8 @@ int kvm_arch_init_vcpu(CPUState *cs) >> return ret; >> } >> >> + kvm_arm_init_debug(cs); >> + >> return kvm_arm_init_cpreg_list(cpu); >> } >> >> diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h >> index 455dea3..a4b480b 100644 >> --- a/target-arm/kvm_arm.h >> +++ b/target-arm/kvm_arm.h >> @@ -162,6 +162,27 @@ typedef struct ARMHostCPUClass { >> */ >> bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc); >> >> +bool kvm_hw_breakpoints_active(CPUState *cs); >> +void kvm_copy_hw_breakpoint_data(struct kvm_guest_debug_arch *ptr); > > If these aren't common-to-all-CPUs functions they should > have an _arm_ in their names. (Otherwise you'd expect > to find kvm_hw_breakpoints_active() next to > kvm_sw_breakpoints_active() in kvm-all.c.) OK thanks > > Also, doc comments for the functions would be nice. > >> + >> +/** >> + * 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 TRUE if the addr matches one of our watchpoints. >> + */ >> +bool kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr); >> + >> #endif >> >> #endif > > thanks > -- PMM -- Alex Benn?e From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40850) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YkXu6-0004z5-A7 for qemu-devel@nongnu.org; Tue, 21 Apr 2015 09:07:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YkXu0-0000Gs-Sa for qemu-devel@nongnu.org; Tue, 21 Apr 2015 09:07:54 -0400 Received: from static.88-198-71-155.clients.your-server.de ([88.198.71.155]:49664 helo=socrates.bennee.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YkXu0-0000GT-Ji for qemu-devel@nongnu.org; Tue, 21 Apr 2015 09:07:48 -0400 References: <1427816446-31586-1-git-send-email-alex.bennee@linaro.org> <1427816446-31586-5-git-send-email-alex.bennee@linaro.org> From: Alex =?utf-8?Q?Benn=C3=A9e?= In-reply-to: Date: Tue, 21 Apr 2015 14:08:04 +0100 Message-ID: <87sibtvdcb.fsf@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Subject: Re: [Qemu-devel] [PATCH v2 4/4] target-arm: kvm - add support for HW assisted debug List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Maydell Cc: kvm-devel , Marc Zyngier , QEMU Developers , Christoffer Dall , Zhichao Huang , Paolo Bonzini , "kvmarm@lists.cs.columbia.edu" , arm-mail-list Peter Maydell writes: > On 31 March 2015 at 16:40, Alex Bennée wrote: >> From: Alex Bennée >> >> 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_BP 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 >> >> diff --git a/target-arm/kvm.c b/target-arm/kvm.c >> index ae0f8b2..d1adf5f 100644 >> --- a/target-arm/kvm.c >> +++ b/target-arm/kvm.c >> @@ -17,6 +17,7 @@ >> >> #include "qemu-common.h" >> #include "qemu/timer.h" >> +#include "qemu/error-report.h" >> #include "sysemu/sysemu.h" >> #include "sysemu/kvm.h" >> #include "kvm_arm.h" >> @@ -476,6 +477,8 @@ void kvm_arch_post_run(CPUState *cs, struct kvm_run *run) >> >> #define HSR_EC_SHIFT 26 >> #define HSR_EC_SOFT_STEP 0x32 >> +#define HSR_EC_HW_BKPT 0x30 >> +#define HSR_EC_HW_WATCH 0x34 >> #define HSR_EC_SW_BKPT 0x3c >> >> static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) >> @@ -496,6 +499,16 @@ static int kvm_handle_debug(CPUState *cs, struct kvm_run *run) >> return true; >> } >> break; >> + case HSR_EC_HW_BKPT: >> + if (kvm_arm_find_hw_breakpoint(cs, arch_info->pc)) { >> + return true; >> + } >> + break; >> + case HSR_EC_HW_WATCH: >> + if (kvm_arm_find_hw_watchpoint(cs, arch_info->far)) { >> + return true; >> + } >> + break; >> default: >> error_report("%s: unhandled debug exit (%x, %llx)\n", >> __func__, arch_info->hsr, arch_info->pc); >> @@ -556,6 +569,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_hw_breakpoints_active(cs)) { >> + dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP; >> + kvm_copy_hw_breakpoint_data(&dbg->arch); >> + } >> } >> >> /* C6.6.29 BRK instruction */ >> @@ -582,26 +599,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; >> -} >> - >> -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 8cf3a62..dbe81a7 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,11 +13,17 @@ >> #include >> #include >> #include >> +#include >> +#include > > We really need the asm/ include ? > >> +#include >> #include >> >> #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" >> @@ -24,6 +31,312 @@ >> #include "internals.h" >> #include "hw/arm/arm.h" >> >> +/* Max and current break/watch point counts */ >> +int max_hw_bp, max_hw_wp; >> +int cur_hw_bp, cur_hw_wp; >> +struct kvm_guest_debug_arch guest_debug_registers; > > How does this work in an SMP guest? Badly I guess ;-) Interesting problem though because GDB only thinks in terms of n breakpoints rather than a per-cpu quantity so I guess we just ensure we have the same set of debug values across all the vcpus? > >> + >> +/** >> + * kvm_arm_init_debug() >> + * @cs: CPUState >> + * >> + * kvm_check_extension returns 0 if we have no debug registers or the >> + * number we have. >> + * >> + */ >> +static void kvm_arm_init_debug(CPUState *cs) >> +{ >> + max_hw_wp = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS); >> + max_hw_bp = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_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) >> +{ >> + uint32_t bcr = 0x1; /* E=1, enable */ >> + if (cur_hw_bp >= max_hw_bp) { >> + return -ENOBUFS; >> + } >> + bcr = deposit32(bcr, 1, 2, 0x3); /* PMC = 11 */ >> + bcr = deposit32(bcr, 5, 4, 0xf); /* BAS = RES1 */ >> + guest_debug_registers.dbg_bcr[cur_hw_bp] = bcr; >> + guest_debug_registers.dbg_bvr[cur_hw_bp] = addr; >> + cur_hw_bp++; >> + 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 < cur_hw_bp; i++) { >> + if (guest_debug_registers.dbg_bvr[i] == pc) { >> + while (i < cur_hw_bp) { >> + if (i == max_hw_bp) { >> + guest_debug_registers.dbg_bvr[i] = 0; >> + guest_debug_registers.dbg_bcr[i] = 0; >> + } else { >> + guest_debug_registers.dbg_bvr[i] = >> + guest_debug_registers.dbg_bvr[i + 1]; >> + guest_debug_registers.dbg_bcr[i] = >> + guest_debug_registers.dbg_bcr[i + 1]; > > Why do we need to shuffle all the registers down > rather than just clearing the enable bit on the one > we stopped using? It keeps it simpler when cur_hw_bp et all are both a count and an index. This is also saves you from having to shuffle them around when packing the $IMPDEF debug registers to the start of the array. > >> + } >> + i++; >> + } >> + cur_hw_bp--; >> + 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 D-12) >> + * 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. Therefor to > > "Therefore" > >> + * break on an sizes smaller than unaligned byte you need to set > > "any". Also what's a size smaller than an unaligned byte? :-) oops, no nibble break points I guess ;-) > >> + * 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) >> +{ >> + uint32_t dbgwcr = 1; /* E=1, enable */ >> + uint64_t dbgwvr = addr & (~0x7ULL); >> + >> + if (cur_hw_wp >= max_hw_wp) { >> + return -ENOBUFS; >> + } >> + >> + /* PAC 00 is reserved, assume EL1 exception */ > > Not sure what this comment is trying to say. PAC value 00 is > reserved, but you're not trying to set it to 00 so that's OK. > >> + dbgwcr = deposit32(dbgwcr, 1, 2, 1); > > Why a PAC value of 1 ? That means we will only get watchpoint > hits for accesses from EL1, which doesn't really seem like > what we want. What you want I think is HMC=0 SSC=0 PAC=3, > which will give you hits for EL0 or EL1, any security state, > valid whether EL3 is implemented or not. Thanks - I didn't find the table as intuitive as I might... > > >> + >> + switch (type) { >> + case GDB_WATCHPOINT_READ: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 1); >> + break; >> + case GDB_WATCHPOINT_WRITE: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 2); >> + break; >> + case GDB_WATCHPOINT_ACCESS: >> + dbgwcr = deposit32(dbgwcr, 3, 2, 3); >> + 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; > > >> + dbgwcr = deposit32(dbgwcr, 5+off, 8-off, bas); > > Missing spaces. > > Given the way deposit32() works you could also say > end = MIN(off + len, 8); > dbgwcr = deposit32(dbgwcr, 5 + off, 5 + end, ~0); > which involves a little less manual bit-twiddling. > > Note that if the unaligned watchpoint we're trying to set > straddles a doubleword boundary (eg a 4-byte watchpoint at > 0x1006) we'll only catch accesses to the first part of it. > That may be OK, I forget what the gdbstub's required > semantics for larger-than-a-byte watchpoints are. If not > you'll need two watchpoint regs to cover both parts. > >> + } else { >> + /* For ranges above 8 bytes we need to be a power of 2 */ >> + if (ctpop64(len)==1) { > > If you want to test whether a number is a power of 2 then > you can use is_power_of_2()... > >> + int bits = ctz64(len); >> + dbgwvr &= ~((1 << bits)-1); > > More spacing issues. > > (Can you actually set a large-range watchpoint with gdb?) I'll double check. > >> + dbgwcr = deposit32(dbgwcr, 24, 4, bits); >> + dbgwcr = deposit32(dbgwcr, 5, 8, 0xff); >> + } else { >> + return -ENOBUFS; >> + } >> + } >> + >> + guest_debug_registers.dbg_wcr[cur_hw_wp] = dbgwcr; >> + guest_debug_registers.dbg_wvr[cur_hw_wp] = dbgwvr; >> + cur_hw_wp++; >> + return 0; >> +} >> + >> + >> +static bool check_watchpoint_in_range(int i, target_ulong addr) >> +{ >> + uint32_t dbgwcr = guest_debug_registers.dbg_wcr[i]; >> + uint64_t addr_top, addr_bottom = guest_debug_registers.dbg_wvr[i]; >> + int bas = extract32(dbgwcr, 5, 8); >> + int mask = extract32(dbgwcr, 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_wp; i++) { >> + if (check_watchpoint_in_range(i, addr)) { >> + while (i < cur_hw_wp) { >> + if (i == max_hw_wp) { >> + guest_debug_registers.dbg_wvr[i] = 0; >> + guest_debug_registers.dbg_wcr[i] = 0; >> + } else { >> + guest_debug_registers.dbg_wvr[i] = >> + guest_debug_registers.dbg_wvr[i + 1]; >> + guest_debug_registers.dbg_wcr[i] = >> + guest_debug_registers.dbg_wcr[i + 1]; >> + } >> + i++; >> + } >> + cur_hw_wp--; >> + 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) >> +{ >> + memset((void *)&guest_debug_registers, 0, sizeof(guest_debug_registers)); > > Do you really need this void* cast? > >> + cur_hw_bp = 0; >> + cur_hw_wp = 0; >> +} >> + >> +void kvm_copy_hw_breakpoint_data(struct kvm_guest_debug_arch *ptr) >> +{ >> + /* Compile time assert? */ > > Better than runtime, but why assert at all, given that we've > simply defined guest_debug_registers to have the right type earlier > and there's nothing likely to make that go subtly wrong? > >> + g_assert(sizeof(struct kvm_guest_debug_arch) == sizeof(guest_debug_registers)); >> + memcpy(ptr, &guest_debug_registers, sizeof(guest_debug_registers)); >> +} >> + >> +bool kvm_hw_breakpoints_active(CPUState *cs) >> +{ >> + return ( (cur_hw_bp > 0) || (cur_hw_wp >0) ) ? TRUE:FALSE; > > You've been reading too much softfloat code, this spacing > style is atrocious :-) Also, true, not TRUE. I'm going to have to investigate Emacs' style settings to see if I can get the spacing automatically... > >> +} >> + >> +bool kvm_arm_find_hw_breakpoint(CPUState *cpu, target_ulong pc) >> +{ >> + if (kvm_hw_breakpoints_active(cpu)) { >> + int i; >> + for (i=0; i> + if (guest_debug_registers.dbg_bvr[i] == pc) { >> + return true; >> + } >> + } >> + } >> + return false; >> +} >> + >> +bool kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr) >> +{ >> + if (kvm_hw_breakpoints_active(cpu)) { >> + int i; >> + for (i=0; i > Spaces! > >> + if (check_watchpoint_in_range(i, addr)) { >> + return true; >> + } >> + } >> + } >> + return false; >> +} >> + >> + >> static inline void set_feature(uint64_t *features, int feature) >> { >> *features |= 1ULL << feature; >> @@ -106,6 +419,8 @@ int kvm_arch_init_vcpu(CPUState *cs) >> return ret; >> } >> >> + kvm_arm_init_debug(cs); >> + >> return kvm_arm_init_cpreg_list(cpu); >> } >> >> diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h >> index 455dea3..a4b480b 100644 >> --- a/target-arm/kvm_arm.h >> +++ b/target-arm/kvm_arm.h >> @@ -162,6 +162,27 @@ typedef struct ARMHostCPUClass { >> */ >> bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc); >> >> +bool kvm_hw_breakpoints_active(CPUState *cs); >> +void kvm_copy_hw_breakpoint_data(struct kvm_guest_debug_arch *ptr); > > If these aren't common-to-all-CPUs functions they should > have an _arm_ in their names. (Otherwise you'd expect > to find kvm_hw_breakpoints_active() next to > kvm_sw_breakpoints_active() in kvm-all.c.) OK thanks > > Also, doc comments for the functions would be nice. > >> + >> +/** >> + * 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 TRUE if the addr matches one of our watchpoints. >> + */ >> +bool kvm_arm_find_hw_watchpoint(CPUState *cpu, target_ulong addr); >> + >> #endif >> >> #endif > > thanks > -- PMM -- Alex Bennée