mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
s390x/mmu: Use ioctl for reading and writing from/to guest memory
Add code to make use of the new ioctl for reading from / writing to virtual guest memory. By using the ioctl, the memory accesses are now protected with the so-called ipte-lock in the kernel. [CH: moved error message into kvm_s390_mem_op()] Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
f07177a559
commit
a9bcd1b871
3 changed files with 54 additions and 0 deletions
|
@ -401,6 +401,8 @@ void kvm_s390_vcpu_interrupt(S390CPU *cpu, struct kvm_s390_irq *irq);
|
||||||
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
|
void kvm_s390_floating_interrupt(struct kvm_s390_irq *irq);
|
||||||
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
|
int kvm_s390_inject_flic(struct kvm_s390_irq *irq);
|
||||||
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
|
void kvm_s390_access_exception(S390CPU *cpu, uint16_t code, uint64_t te_code);
|
||||||
|
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len,
|
||||||
|
bool is_write);
|
||||||
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||||
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_clock);
|
||||||
#else
|
#else
|
||||||
|
@ -418,6 +420,11 @@ static inline int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
static inline int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf,
|
||||||
|
int len, bool is_write)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
|
static inline void kvm_s390_access_exception(S390CPU *cpu, uint16_t code,
|
||||||
uint64_t te_code)
|
uint64_t te_code)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,6 +123,7 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
|
||||||
|
|
||||||
static int cap_sync_regs;
|
static int cap_sync_regs;
|
||||||
static int cap_async_pf;
|
static int cap_async_pf;
|
||||||
|
static int cap_mem_op;
|
||||||
|
|
||||||
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
static void *legacy_s390_alloc(size_t size, uint64_t *align);
|
||||||
|
|
||||||
|
@ -247,6 +248,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||||
{
|
{
|
||||||
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
|
cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS);
|
||||||
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
|
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
|
||||||
|
cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
|
||||||
|
|
||||||
kvm_s390_enable_cmma(s);
|
kvm_s390_enable_cmma(s);
|
||||||
|
|
||||||
|
@ -550,6 +552,44 @@ int kvm_s390_set_clock(uint8_t *tod_high, uint64_t *tod_low)
|
||||||
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* kvm_s390_mem_op:
|
||||||
|
* @addr: the logical start address in guest memory
|
||||||
|
* @hostbuf: buffer in host memory. NULL = do only checks w/o copying
|
||||||
|
* @len: length that should be transfered
|
||||||
|
* @is_write: true = write, false = read
|
||||||
|
* Returns: 0 on success, non-zero if an exception or error occured
|
||||||
|
*
|
||||||
|
* Use KVM ioctl to read/write from/to guest memory. An access exception
|
||||||
|
* is injected into the vCPU in case of translation errors.
|
||||||
|
*/
|
||||||
|
int kvm_s390_mem_op(S390CPU *cpu, vaddr addr, void *hostbuf, int len,
|
||||||
|
bool is_write)
|
||||||
|
{
|
||||||
|
struct kvm_s390_mem_op mem_op = {
|
||||||
|
.gaddr = addr,
|
||||||
|
.flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION,
|
||||||
|
.size = len,
|
||||||
|
.op = is_write ? KVM_S390_MEMOP_LOGICAL_WRITE
|
||||||
|
: KVM_S390_MEMOP_LOGICAL_READ,
|
||||||
|
.buf = (uint64_t)hostbuf,
|
||||||
|
};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cap_mem_op) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
if (!hostbuf) {
|
||||||
|
mem_op.flags |= KVM_S390_MEMOP_F_CHECK_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_S390_MEM_OP, &mem_op);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_printf("KVM_S390_MEM_OP failed: %s\n", strerror(-ret));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Legacy layout for s390:
|
* Legacy layout for s390:
|
||||||
* Older S390 KVM requires the topmost vma of the RAM to be
|
* Older S390 KVM requires the topmost vma of the RAM to be
|
||||||
|
|
|
@ -450,6 +450,13 @@ int s390_cpu_virt_mem_rw(S390CPU *cpu, vaddr laddr, void *hostbuf,
|
||||||
target_ulong *pages;
|
target_ulong *pages;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
ret = kvm_s390_mem_op(cpu, laddr, hostbuf, len, is_write);
|
||||||
|
if (ret >= 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
|
nr_pages = (((laddr & ~TARGET_PAGE_MASK) + len - 1) >> TARGET_PAGE_BITS)
|
||||||
+ 1;
|
+ 1;
|
||||||
pages = g_malloc(nr_pages * sizeof(*pages));
|
pages = g_malloc(nr_pages * sizeof(*pages));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue