aboutsummaryrefslogtreecommitdiff
path: root/target-s390x
diff options
context:
space:
mode:
Diffstat (limited to 'target-s390x')
-rw-r--r--target-s390x/Makefile.objs5
-rw-r--r--target-s390x/cpu.c2
-rw-r--r--target-s390x/cpu.h10
-rw-r--r--target-s390x/helper.c13
-rw-r--r--target-s390x/kvm.c48
-rw-r--r--target-s390x/translate.c2
6 files changed, 59 insertions, 21 deletions
diff --git a/target-s390x/Makefile.objs b/target-s390x/Makefile.objs
new file mode 100644
index 0000000000..262747f8a6
--- /dev/null
+++ b/target-s390x/Makefile.objs
@@ -0,0 +1,5 @@
+obj-y += translate.o op_helper.o helper.o cpu.o
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.o
+
+$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index f183213eab..619b202b92 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -20,7 +20,7 @@
* <http://www.gnu.org/licenses/lgpl-2.1.html>
*/
-#include "cpu-qom.h"
+#include "cpu.h"
#include "qemu-common.h"
#include "qemu-timer.h"
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2f3f3942c0..c30ac3a0e1 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -105,6 +105,8 @@ typedef struct CPUS390XState {
QEMUTimer *cpu_timer;
} CPUS390XState;
+#include "cpu-qom.h"
+
#if defined(CONFIG_USER_ONLY)
static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp)
{
@@ -271,7 +273,7 @@ static inline int get_ilc(uint8_t opc)
#define ILC_LATER_INC_2 0x22
-CPUS390XState *cpu_s390x_init(const char *cpu_model);
+S390CPU *cpu_s390x_init(const char *cpu_model);
void s390x_translate_init(void);
int cpu_s390x_exec(CPUS390XState *s);
void cpu_s390x_close(CPUS390XState *s);
@@ -314,7 +316,7 @@ static inline void kvm_s390_interrupt_internal(CPUS390XState *env, int type,
{
}
#endif
-CPUS390XState *s390_cpu_addr2state(uint16_t cpu_addr);
+S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
void s390_add_running_cpu(CPUS390XState *env);
unsigned s390_del_running_cpu(CPUS390XState *env);
@@ -340,7 +342,7 @@ static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls)
env->aregs[1] = newtls & 0xffffffffULL;
}
-#define cpu_init cpu_s390x_init
+#define cpu_init(model) (&cpu_s390x_init(model)->env)
#define cpu_exec cpu_s390x_exec
#define cpu_gen_code cpu_s390x_gen_code
#define cpu_signal_handler cpu_s390x_signal_handler
@@ -994,6 +996,4 @@ static inline void cpu_pc_from_tb(CPUS390XState *env, TranslationBlock* tb)
env->psw.addr = tb->pc;
}
-#include "cpu-qom.h"
-
#endif
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 209a69603c..d0a1180a83 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -70,7 +70,7 @@ void s390x_cpu_timer(void *opaque)
}
#endif
-CPUS390XState *cpu_s390x_init(const char *cpu_model)
+S390CPU *cpu_s390x_init(const char *cpu_model)
{
S390CPU *cpu;
CPUS390XState *env;
@@ -86,7 +86,7 @@ CPUS390XState *cpu_s390x_init(const char *cpu_model)
env->cpu_model_str = cpu_model;
qemu_init_vcpu(env);
- return env;
+ return cpu;
}
#if defined(CONFIG_USER_ONLY)
@@ -106,14 +106,7 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
return 1;
}
-#endif /* CONFIG_USER_ONLY */
-
-void cpu_state_reset(CPUS390XState *env)
-{
- cpu_reset(ENV_GET_CPU(env));
-}
-
-#ifndef CONFIG_USER_ONLY
+#else /* !CONFIG_USER_ONLY */
/* Ensure to exit the TB after this call! */
static void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilc)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 90aad61eb0..47008c24f2 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -135,6 +135,41 @@ int kvm_arch_get_registers(CPUS390XState *env)
return 0;
}
+/*
+ * Legacy layout for s390:
+ * Older S390 KVM requires the topmost vma of the RAM to be
+ * smaller than an system defined value, which is at least 256GB.
+ * Larger systems have larger values. We put the guest between
+ * the end of data segment (system break) and this value. We
+ * use 32GB as a base to have enough room for the system break
+ * to grow. We also have to use MAP parameters that avoid
+ * read-only mapping of guest pages.
+ */
+static void *legacy_s390_alloc(ram_addr_t size)
+{
+ void *mem;
+
+ mem = mmap((void *) 0x800000000ULL, size,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+ if (mem == MAP_FAILED) {
+ fprintf(stderr, "Allocating RAM failed\n");
+ abort();
+ }
+ return mem;
+}
+
+void *kvm_arch_vmalloc(ram_addr_t size)
+{
+ /* Can we use the standard allocation ? */
+ if (kvm_check_extension(kvm_state, KVM_CAP_S390_GMAP) &&
+ kvm_check_extension(kvm_state, KVM_CAP_S390_COW)) {
+ return NULL;
+ } else {
+ return legacy_s390_alloc(size);
+ }
+}
+
int kvm_arch_insert_sw_breakpoint(CPUS390XState *env, struct kvm_sw_breakpoint *bp)
{
static const uint8_t diag_501[] = {0x83, 0x24, 0x05, 0x01};
@@ -292,8 +327,10 @@ static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code)
return r;
}
-static int s390_cpu_restart(CPUS390XState *env)
+static int s390_cpu_restart(S390CPU *cpu)
{
+ CPUS390XState *env = &cpu->env;
+
kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
s390_add_running_cpu(env);
qemu_cpu_kick(env);
@@ -312,6 +349,7 @@ static int s390_cpu_initial_reset(CPUS390XState *env)
{
int i;
+ s390_del_running_cpu(env);
if (kvm_vcpu_ioctl(env, KVM_S390_INITIAL_RESET, NULL) < 0) {
perror("cannot init reset vcpu");
}
@@ -333,6 +371,7 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
uint16_t cpu_addr;
uint8_t t;
int r = -1;
+ S390CPU *target_cpu;
CPUS390XState *target_env;
cpu_synchronize_state(env);
@@ -353,14 +392,15 @@ static int handle_sigp(CPUS390XState *env, struct kvm_run *run, uint8_t ipa1)
parameter = env->regs[t] & 0x7ffffe00;
cpu_addr = env->regs[ipa1 & 0x0f];
- target_env = s390_cpu_addr2state(cpu_addr);
- if (!target_env) {
+ target_cpu = s390_cpu_addr2state(cpu_addr);
+ if (target_cpu == NULL) {
goto out;
}
+ target_env = &target_cpu->env;
switch (order_code) {
case SIGP_RESTART:
- r = s390_cpu_restart(target_env);
+ r = s390_cpu_restart(target_cpu);
break;
case SIGP_STORE_STATUS_ADDR:
r = s390_store_status(target_env, parameter);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 9bf8c38bb3..1c1baf5342 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -5098,7 +5098,7 @@ static void disas_s390_insn(DisasContext *s)
disas_ed(s, op, r1, x2, b2, d2, r1b);
break;
default:
- LOG_DISAS("unimplemented opcode 0x%x\n", opc);
+ qemu_log_mask(LOG_UNIMP, "unimplemented opcode 0x%x\n", opc);
gen_illegal_opcode(s, ilc);
break;
}