mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 1687949 - Make the vector load/store instructions fault properly. r=nbp
Two fixes here: First, every time we try to execute a vector memory instruction, check if the access would fault, and bail out in the standard manner if it would. Second, fix a bug in the implementation of the NEON decoder where some load instructions would be executed twice. If the first execution faults then the fault handler moves the PC, and then the second fault will crash hard. The fix here has been imported from upstream, more or less. Differential Revision: https://phabricator.services.mozilla.com/D102600
This commit is contained in:
parent
9da69d2038
commit
c07ec516ea
@ -97,6 +97,8 @@ float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
|
||||
void Simulator::ld1(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, 16))
|
||||
return;
|
||||
dst.ClearForWrite(vform);
|
||||
for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
||||
dst.ReadUintFromMem(vform, i, addr);
|
||||
@ -109,6 +111,8 @@ void Simulator::ld1(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
int index,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
|
||||
return;
|
||||
dst.ReadUintFromMem(vform, index, addr);
|
||||
}
|
||||
|
||||
@ -116,6 +120,8 @@ void Simulator::ld1(VectorFormat vform,
|
||||
void Simulator::ld1r(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
|
||||
return;
|
||||
dst.ClearForWrite(vform);
|
||||
for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
||||
dst.ReadUintFromMem(vform, i, addr);
|
||||
@ -127,6 +133,8 @@ void Simulator::ld2(VectorFormat vform,
|
||||
LogicVRegister dst1,
|
||||
LogicVRegister dst2,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, 16*2))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
@ -145,6 +153,8 @@ void Simulator::ld2(VectorFormat vform,
|
||||
LogicVRegister dst2,
|
||||
int index,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*2))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
uint64_t addr2 = addr1 + LaneSizeInBytesFromFormat(vform);
|
||||
@ -157,6 +167,8 @@ void Simulator::ld2r(VectorFormat vform,
|
||||
LogicVRegister dst1,
|
||||
LogicVRegister dst2,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*2))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
uint64_t addr2 = addr + LaneSizeInBytesFromFormat(vform);
|
||||
@ -172,6 +184,8 @@ void Simulator::ld3(VectorFormat vform,
|
||||
LogicVRegister dst2,
|
||||
LogicVRegister dst3,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, 16*3))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -195,6 +209,8 @@ void Simulator::ld3(VectorFormat vform,
|
||||
LogicVRegister dst3,
|
||||
int index,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*3))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -211,6 +227,8 @@ void Simulator::ld3r(VectorFormat vform,
|
||||
LogicVRegister dst2,
|
||||
LogicVRegister dst3,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*3))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -230,6 +248,8 @@ void Simulator::ld4(VectorFormat vform,
|
||||
LogicVRegister dst3,
|
||||
LogicVRegister dst4,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, 16*4))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -258,6 +278,8 @@ void Simulator::ld4(VectorFormat vform,
|
||||
LogicVRegister dst4,
|
||||
int index,
|
||||
uint64_t addr1) {
|
||||
if (handle_wasm_seg_fault(addr1, LaneSizeInBytesFromFormat(vform)*4))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -278,6 +300,8 @@ void Simulator::ld4r(VectorFormat vform,
|
||||
LogicVRegister dst3,
|
||||
LogicVRegister dst4,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*4))
|
||||
return;
|
||||
dst1.ClearForWrite(vform);
|
||||
dst2.ClearForWrite(vform);
|
||||
dst3.ClearForWrite(vform);
|
||||
@ -297,6 +321,8 @@ void Simulator::ld4r(VectorFormat vform,
|
||||
void Simulator::st1(VectorFormat vform,
|
||||
LogicVRegister src,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, 16))
|
||||
return;
|
||||
for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
||||
src.WriteUintToMem(vform, i, addr);
|
||||
addr += LaneSizeInBytesFromFormat(vform);
|
||||
@ -308,6 +334,8 @@ void Simulator::st1(VectorFormat vform,
|
||||
LogicVRegister src,
|
||||
int index,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)))
|
||||
return;
|
||||
src.WriteUintToMem(vform, index, addr);
|
||||
}
|
||||
|
||||
@ -316,6 +344,8 @@ void Simulator::st2(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
LogicVRegister dst2,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, 16*2))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
uint64_t addr2 = addr + esize;
|
||||
for (int i = 0; i < LaneCountFromFormat(vform); i++) {
|
||||
@ -332,6 +362,8 @@ void Simulator::st2(VectorFormat vform,
|
||||
LogicVRegister dst2,
|
||||
int index,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*2))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
dst.WriteUintToMem(vform, index, addr);
|
||||
dst2.WriteUintToMem(vform, index, addr + 1 * esize);
|
||||
@ -343,6 +375,8 @@ void Simulator::st3(VectorFormat vform,
|
||||
LogicVRegister dst2,
|
||||
LogicVRegister dst3,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, 16*3))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
uint64_t addr2 = addr + esize;
|
||||
uint64_t addr3 = addr2 + esize;
|
||||
@ -363,6 +397,8 @@ void Simulator::st3(VectorFormat vform,
|
||||
LogicVRegister dst3,
|
||||
int index,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*3))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
dst.WriteUintToMem(vform, index, addr);
|
||||
dst2.WriteUintToMem(vform, index, addr + 1 * esize);
|
||||
@ -376,6 +412,8 @@ void Simulator::st4(VectorFormat vform,
|
||||
LogicVRegister dst3,
|
||||
LogicVRegister dst4,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, 16*4))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
uint64_t addr2 = addr + esize;
|
||||
uint64_t addr3 = addr2 + esize;
|
||||
@ -400,6 +438,8 @@ void Simulator::st4(VectorFormat vform,
|
||||
LogicVRegister dst4,
|
||||
int index,
|
||||
uint64_t addr) {
|
||||
if (handle_wasm_seg_fault(addr, LaneSizeInBytesFromFormat(vform)*4))
|
||||
return;
|
||||
int esize = LaneSizeInBytesFromFormat(vform);
|
||||
dst.WriteUintToMem(vform, index, addr);
|
||||
dst2.WriteUintToMem(vform, index, addr + 1 * esize);
|
||||
|
@ -3056,6 +3056,8 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
// and PostIndex addressing.
|
||||
bool do_load = false;
|
||||
|
||||
bool replicating = false;
|
||||
|
||||
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
|
||||
VectorFormat vf_t = nfd.GetVectorFormat();
|
||||
|
||||
@ -3124,40 +3126,16 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
}
|
||||
|
||||
case NEON_LD1R:
|
||||
case NEON_LD1R_post: {
|
||||
vf = vf_t;
|
||||
ld1r(vf, vreg(rt), addr);
|
||||
do_load = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NEON_LD1R_post:
|
||||
case NEON_LD2R:
|
||||
case NEON_LD2R_post: {
|
||||
vf = vf_t;
|
||||
int rt2 = (rt + 1) % kNumberOfVRegisters;
|
||||
ld2r(vf, vreg(rt), vreg(rt2), addr);
|
||||
do_load = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NEON_LD2R_post:
|
||||
case NEON_LD3R:
|
||||
case NEON_LD3R_post: {
|
||||
vf = vf_t;
|
||||
int rt2 = (rt + 1) % kNumberOfVRegisters;
|
||||
int rt3 = (rt2 + 1) % kNumberOfVRegisters;
|
||||
ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
|
||||
do_load = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NEON_LD3R_post:
|
||||
case NEON_LD4R:
|
||||
case NEON_LD4R_post: {
|
||||
vf = vf_t;
|
||||
int rt2 = (rt + 1) % kNumberOfVRegisters;
|
||||
int rt3 = (rt2 + 1) % kNumberOfVRegisters;
|
||||
int rt4 = (rt3 + 1) % kNumberOfVRegisters;
|
||||
ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
|
||||
do_load = true;
|
||||
replicating = true;
|
||||
break;
|
||||
}
|
||||
default: VIXL_UNIMPLEMENTED();
|
||||
@ -3180,7 +3158,11 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
case NEONLoadStoreSingle1:
|
||||
scale = 1;
|
||||
if (do_load) {
|
||||
ld1(vf, vreg(rt), lane, addr);
|
||||
if (replicating) {
|
||||
ld1r(vf, vreg(rt), addr);
|
||||
} else {
|
||||
ld1(vf, vreg(rt), lane, addr);
|
||||
}
|
||||
LogVRead(addr, rt, print_format, lane);
|
||||
} else {
|
||||
st1(vf, vreg(rt), lane, addr);
|
||||
@ -3190,7 +3172,11 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
case NEONLoadStoreSingle2:
|
||||
scale = 2;
|
||||
if (do_load) {
|
||||
ld2(vf, vreg(rt), vreg(rt2), lane, addr);
|
||||
if (replicating) {
|
||||
ld2r(vf, vreg(rt), vreg(rt2), addr);
|
||||
} else {
|
||||
ld2(vf, vreg(rt), vreg(rt2), lane, addr);
|
||||
}
|
||||
LogVRead(addr, rt, print_format, lane);
|
||||
LogVRead(addr + esize, rt2, print_format, lane);
|
||||
} else {
|
||||
@ -3202,7 +3188,11 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
case NEONLoadStoreSingle3:
|
||||
scale = 3;
|
||||
if (do_load) {
|
||||
ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
|
||||
if (replicating) {
|
||||
ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
|
||||
} else {
|
||||
ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
|
||||
}
|
||||
LogVRead(addr, rt, print_format, lane);
|
||||
LogVRead(addr + esize, rt2, print_format, lane);
|
||||
LogVRead(addr + (2 * esize), rt3, print_format, lane);
|
||||
@ -3216,7 +3206,11 @@ void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
|
||||
case NEONLoadStoreSingle4:
|
||||
scale = 4;
|
||||
if (do_load) {
|
||||
ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
|
||||
if (replicating) {
|
||||
ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
|
||||
} else {
|
||||
ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
|
||||
}
|
||||
LogVRead(addr, rt, print_format, lane);
|
||||
LogVRead(addr + esize, rt2, print_format, lane);
|
||||
LogVRead(addr + (2 * esize), rt3, print_format, lane);
|
||||
|
Loading…
Reference in New Issue
Block a user