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:
Lars T Hansen 2021-01-27 11:35:48 +00:00
parent 9da69d2038
commit c07ec516ea
2 changed files with 66 additions and 32 deletions

View File

@ -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);

View File

@ -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);