diff --git a/thermosphere/src/exception_vectors.s b/thermosphere/src/exception_vectors.s index abde290e7..fa706d017 100644 --- a/thermosphere/src/exception_vectors.s +++ b/thermosphere/src/exception_vectors.s @@ -152,11 +152,8 @@ vector_entry _synchSp0 eret _handleSafecpy: - // Set Z flag - mrs x18, spsr_el2 - orr x18, x18, #(1 << 30) - msr spsr_el2, x18 - mov x18, #0 + // Set x16 to 1 + mov x16, #1 eret check_vector_size _synchSp0 diff --git a/thermosphere/src/hvisor_safe_io_copy.hpp b/thermosphere/src/hvisor_safe_io_copy.hpp new file mode 100644 index 000000000..b55f3a045 --- /dev/null +++ b/thermosphere/src/hvisor_safe_io_copy.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "defines.hpp" + +namespace ams::hvisor { + + // Caller needs to disable interrupts + size_t SafeIoCopy(void *dst, const void *src, size_t size); + +} diff --git a/thermosphere/src/hvisor_safe_io_copy.s b/thermosphere/src/hvisor_safe_io_copy.s new file mode 100644 index 000000000..fe7fafbdc --- /dev/null +++ b/thermosphere/src/hvisor_safe_io_copy.s @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "asm_macros.s" + +// ams::hvisor::SafeIoCopy(void*, void const*, unsigned long) +FUNCTION _ZN3ams6hvisor10SafeIoCopyEPvPKvm + // Caller needs to mask interrupts + // See _synchSp0 exception handler + msr spsel, #0 + mov x9, x18 + mov x18, #0 + mov x16, #0 + + // x0-x2 parameters + // x3: remainder + // x4: offset + + cbz x2, 2f + mov x3, x2 + mov x4, #0 + + mov x5, #0 + // while (remainder > 0) { offset += increment; test alignment etc. } return offset; + 1: + // Dispatcher + add x5, x1, x4 + add x6, x0, x4 + orr x7, x5, x6 + tst x7, #3 + // ((src + off)|(dst + off)) & 3 == 0 ? remainder > 3 : eq + ccmp x3, #3, #0, eq + bhi 3f + // same thing but for 2-byte alignment + cmp x3, #1 + cset w8, hi + bics wzr, w8, w5 + bne 4f + + // 8-bit load, if the load and/or store crashes, x16 = 1 (same thing for the other load/stores) + ldrb w5, [x5] + strb w5, [x6] + cbnz x16, 2f + add x4, x4, #1 + subs x3, x3, #1 + bne 1b + 2: + // Return + msr spsel, #1 + mov x18, x9 + mov x0, x4 + ret + 3: + // 32-bit load + ldr w5, [x5] + str w5, [x6] + cbnz x16, 2b + add x4, x4, #4 + subs x3, x3, #4 + bne 1b + b 2b + 4: + // 16-bit load + ldrh w5, [x5] + strh w5, [x6] + cbnz x16, 2b + add x4, x4, #2 + subs x3, x3, #2 + bne 1b + b 2b +END_FUNCTION