Subject: [PATCH/RFC 2/5] s390 zlive privileged instructions

From: Carsten Otte <[EMAIL PROTECTED]>
From: Christian Borntraeger <[EMAIL PROTECTED]>

This patch adds two things to the base code:
o infrastructure for handling priviledged operations
o handlers for basic priv ops, which are necessary to run Linux

Most handlers follow the behaviour defined in Principles of Operation.
Some handlers (e.g. store system information) provide only a limited subset
of the functionality, just enough to make things work.

We do not provide functionality for classic channel subsystem I/O, instead we
return condition code 3 on store subchannel. We use paravirtualized drivers
as we currently dont need full device virtualization.

Signed-off-by: Carsten Otte <[EMAIL PROTECTED]>
---
 include/system_info.h              |   89 +++++++++++
 include/zlpriv.h                   |   30 +++
 priv/Makefile                      |   25 +++
 priv/chsc.c                        |   28 +++
 priv/insert_storage_key_extended.c |   30 +++
 priv/priv.c                        |   46 +++++
 priv/set_prefix.c                  |   43 +++++
 priv/set_storage_key_extended.c    |   32 ++++
 priv/store_cpu_address.c           |   34 ++++
 priv/store_cpu_id.c                |   86 +++++++++++
 priv/store_facility_list.c         |   31 ++++
 priv/store_prefix.c                |   32 ++++
 priv/store_subchannel.c            |   27 +++
 priv/store_system_info.c           |  284 +++++++++++++++++++++++++++++++++++++
 14 files changed, 817 insertions(+)

Index: zlive/include/system_info.h
===================================================================
--- /dev/null
+++ zlive/include/system_info.h
@@ -0,0 +1,89 @@
+/*
+ * z/Live store system information privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#ifndef __system_info_h__
+#define __system_info_h__
+struct sysinfo_1_1_1
+{
+        char reserved_0[32];
+        char manufacturer[16];
+        char type[4];
+        char reserved_1[12];
+        char model[16];
+        char sequence[16];
+        char plant[4];
+};
+
+struct sysinfo_1_2_1
+{
+        char reserved_0[80];
+        char sequence[16];
+        char plant[4];
+        char reserved_1[2];
+        unsigned short cpu_address;
+};
+
+struct sysinfo_1_2_2
+{
+        char reserved_0[32];
+        unsigned int capability;
+        unsigned short cpus_total;
+        unsigned short cpus_configured;
+        unsigned short cpus_standby;
+        unsigned short cpus_reserved;
+        unsigned short adjustment[0];
+};
+
+struct sysinfo_2_2_1
+{
+        char reserved_0[80];
+        char sequence[16];
+        char plant[4];
+        unsigned short cpu_id;
+        unsigned short cpu_address;
+};
+
+struct sysinfo_2_2_2
+{
+        char reserved_0[32];
+        unsigned short lpar_number;
+        char reserved_1;
+        unsigned char characteristics;
+        #define LPAR_CHAR_DEDICATED     (1 << 7)
+        #define LPAR_CHAR_SHARED        (1 << 6)
+        #define LPAR_CHAR_LIMITED       (1 << 5)
+        unsigned short cpus_total;
+        unsigned short cpus_configured;
+        unsigned short cpus_standby;
+        unsigned short cpus_reserved;
+        char name[8];
+        unsigned int caf;
+        char reserved_2[16];
+        unsigned short cpus_dedicated;
+        unsigned short cpus_shared;
+};
+
+struct sysinfo_3_2_2
+{
+        char reserved_0[31];
+        unsigned char count;
+        struct
+        {
+                char reserved_0[4];
+                unsigned short cpus_total;
+                unsigned short cpus_configured;
+                unsigned short cpus_standby;
+                unsigned short cpus_reserved;
+                char name[8];
+                unsigned int caf;
+                char cpi[16];
+                char reserved_1[24];
+
+        } vm[8];
+};
+#endif
Index: zlive/include/zlpriv.h
===================================================================
--- /dev/null
+++ zlive/include/zlpriv.h
@@ -0,0 +1,30 @@
+/*
+ * z/Live privileged instruction header file
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#ifndef __ZLPRIV_H
+#define __ZLPRIV_H
+#include <zlintercept.h>
+
+//opcode minors for privileged instructions
+#define PRIV_STORE_CPU_ID                 0x02
+#define PRIV_SET_PREFIX                   0x10
+#define PRIV_STORE_PREFIX                 0x11
+#define PRIV_STORE_CPU_ADDRESS            0x12
+#define PRIV_SCLP_CALL                    0x20
+#define PRIV_INSERT_STORAGE_KEY_EXTENDED  0x29
+#define PRIV_SET_STORAGE_KEY_EXTENDED     0x2b
+#define PRIV_STORE_SUBCHANNEL             0x34
+#define PRIV_CSP                          0x50
+#define PRIV_CHSC                         0x5f
+#define PRIV_STORE_SYSTEM_INFORMATION     0x7D
+#define PRIV_STORE_FACILITY_LIST          0xb1
+
+void register_privileged_handler (unsigned char ocminor, intercept_handler_t 
handler);
+void init_priv ();
+
+#endif
Index: zlive/priv/Makefile
===================================================================
--- /dev/null
+++ zlive/priv/Makefile
@@ -0,0 +1,25 @@
+# z/Live privileged instruction makefile
+# Copyright IBM Corp. 2007
+# Author: Carsten Otte <[EMAIL PROTECTED]>
+# This file is licensed under the terms of the GNU General Public License(GPL)
+
+%.o : %.c ; echo "     Compiling       " $<; $(CC) $(CFLAGS) -c $<
+
+OBJS := chsc.o insert_storage_key_extended.o priv.o priv_autoinit.o 
set_prefix.o set_storage_key_extended.o store_cpu_address.o store_cpu_id.o 
store_facility_list.o store_prefix.o store_subchannel.o store_system_info.o
+
+all: $(OBJS)
+clean:
+       rm -f $(OBJS) priv_autoinit.c
+
+priv_autoinit.c: chsc.c insert_storage_key_extended.c set_prefix.c 
set_storage_key_extended.c store_cpu_address.c store_cpu_id.c 
store_facility_list.c store_prefix.c store_subchannel.c store_system_info.c
+       echo "  Creating        " $@
+       echo "//Makefile generated" >$@
+       echo "#define __ZLAUTOINIT(f) void f(void);" >>$@
+       cat $^ |grep __ZLAUTOINIT >>$@
+       echo "#undef __ZLAUTOINIT" >>$@
+       echo "#define __ZLAUTOINIT(f) { f(); };" >>$@
+       echo "void autoinit_priv(void) {" >>$@
+       cat $^ |grep __ZLAUTOINIT >>$@
+       echo "}" >>$@
+
+.PHONY: clean all
Index: zlive/priv/chsc.c
===================================================================
--- /dev/null
+++ zlive/priv/chsc.c
@@ -0,0 +1,28 @@
+/*
+ * z/Live channel subsystem call privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+
+
+static int priv_chsc(struct zlcpu *cpu)
+{
+
+       debug("cpu %d: channel subsystem call at %lx", cpu->cpuno, 
cl_get_psw(cpu).addr);
+       setcc(cpu, 3);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_chsc_init(void)
+{
+       register_privileged_handler (PRIV_CHSC, priv_chsc);
+}
+
+__ZLAUTOINIT(priv_chsc_init)
Index: zlive/priv/insert_storage_key_extended.c
===================================================================
--- /dev/null
+++ zlive/priv/insert_storage_key_extended.c
@@ -0,0 +1,30 @@
+/*
+ * z/Live insert storage key extended privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <sys/ioctl.h>
+
+#include <zlglobals.h>
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+
+static int priv_insert_storage_key_extended(struct zlcpu *cpu)
+{
+       cpu->input->iske_parm.sk_reg = (cl_get_ipbh0(cpu) & 0xf0) >> 4;
+       cpu->input->iske_parm.sk_addr = cpu->gpr->regs[cl_get_ipbh0(cpu) & 0xf];
+       cpu->input_flags |= SIE_ISKE;
+       debug ("cpu %d: iske", cpu->cpuno);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_insert_storage_key_extended_init(void)
+{
+       register_privileged_handler (PRIV_INSERT_STORAGE_KEY_EXTENDED, 
priv_insert_storage_key_extended);
+}
+
+__ZLAUTOINIT(priv_insert_storage_key_extended_init)
Index: zlive/priv/priv.c
===================================================================
--- /dev/null
+++ zlive/priv/priv.c
@@ -0,0 +1,46 @@
+/*
+ * z/Live privileged instruction interceptions
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <string.h>
+
+#include <zlintercept.h>
+#include <zlinstruction.h>
+#include <zlpriv.h>
+#include <zlmessage.h>
+#include <zlautoinit.h>
+#include <zlcpu_lib.h>
+
+
+static intercept_handler_t priv_handlers[256];
+
+int handle_priv(struct zlcpu *cpu)
+{
+       if (priv_handlers[cl_get_ipa1(cpu)]) {
+               debug ("cpu %d: processing privileged instruction b2%02x at 
addr %lx",
+                      cpu->cpuno, cl_get_ipa1(cpu), cl_get_psw(cpu).addr);
+               return priv_handlers[cl_get_ipa1(cpu)](cpu);
+       }
+       log ("cpu %d: unknown privileged instruction b2%02x at addr %lx, 
sending prog 1",
+            cpu->cpuno, cl_get_ipa1(cpu), cl_get_psw(cpu).addr);
+       return enter_pgmcheck (cpu, 0x0001);
+}
+
+void register_privileged_handler(unsigned char code, intercept_handler_t 
handler)
+{
+       if (priv_handlers[code])
+               report_it ("priv handler registered twice");
+       priv_handlers[code] = handler;
+}
+
+void init_priv(void)
+{
+       memset (priv_handlers, 0, 256*sizeof(intercept_handler_t));
+       autoinit_priv(); // see makefile magic
+       register_instruction_handler(OPCODE_MAJOR_PRIV, handle_priv);
+}
Index: zlive/priv/set_prefix.c
===================================================================
--- /dev/null
+++ zlive/priv/set_prefix.c
@@ -0,0 +1,43 @@
+/*
+ * z/Live set prefix privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <sys/ioctl.h>
+
+static int priv_set_prefix(struct zlcpu *cpu)
+{
+       unsigned long target;
+       unsigned int prefix;
+
+       target = decode_base_displacement(cpu);
+       target = apply_prefixing(cpu, target);
+
+       check_addr(cpu, target);
+
+       /* copy bits 1-18 from the specified address to the prefix register*/
+       prefix =
+               ((*(uint32_t *) (target + glo_origin)) & 0x7fffe000u) |
+               (cl_get_prefix(cpu) & 0x80001fffu);
+       cl_set_prefix(cpu, prefix);
+
+        cpu->input_flags |= SIE_FLUSH_TLB;
+
+       debug("cpu %d: prefix page set to %x at addr %lx", cpu->cpuno, 
cl_get_prefix(cpu), cl_get_psw(cpu).addr);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_set_prefix_init(void)
+{
+       register_privileged_handler (PRIV_SET_PREFIX, priv_set_prefix);
+}
+
+__ZLAUTOINIT(priv_set_prefix_init)
Index: zlive/priv/set_storage_key_extended.c
===================================================================
--- /dev/null
+++ zlive/priv/set_storage_key_extended.c
@@ -0,0 +1,32 @@
+/*
+ * z/Live set storage key extended privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <sys/ioctl.h>
+
+#include <zlglobals.h>
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+
+static int priv_set_storage_key_extended(struct zlcpu *cpu)
+{
+       cpu->input->sske_parm.sk_reg = (cl_get_ipbh0(cpu) & 0xf0) >> 4;
+       cpu->input->sske_parm.sk_addr = cpu->gpr->regs[cl_get_ipbh0(cpu) & 0xf];
+       cpu->input_flags |= SIE_SSKE;
+       debug ("cpu %d: sske at addr %lx",
+              cpu->cpuno, cl_get_psw(cpu).addr);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_set_storage_key_extended_init(void)
+{
+       register_privileged_handler (PRIV_SET_STORAGE_KEY_EXTENDED, 
priv_set_storage_key_extended);
+}
+
+__ZLAUTOINIT(priv_set_storage_key_extended_init)
Index: zlive/priv/store_cpu_address.c
===================================================================
--- /dev/null
+++ zlive/priv/store_cpu_address.c
@@ -0,0 +1,34 @@
+/*
+ * z/Live store cpu address privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+
+static int priv_store_cpu_address (struct zlcpu *cpu)
+{
+       uint64_t reg;
+       uint16_t *target;
+
+       reg = decode_base_displacement(cpu);
+       reg = apply_prefixing(cpu, reg);
+
+       check_addr(cpu, reg);
+       target = (uint16_t *) (reg + glo_origin);
+       *target = cpu->cpuno;
+
+       return may_do_cpu_work(cpu);
+}
+
+void priv_store_cpu_address_init(void)
+{
+       register_privileged_handler (PRIV_STORE_CPU_ADDRESS, 
priv_store_cpu_address);
+}
+
+__ZLAUTOINIT(priv_store_cpu_address_init)
Index: zlive/priv/store_cpu_id.c
===================================================================
--- /dev/null
+++ zlive/priv/store_cpu_id.c
@@ -0,0 +1,86 @@
+/*
+ * z/Live store cpu id privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlconfig.h>
+
+struct cpu_id {
+       uint8_t version;        /* ff=z/VM, fe=z/LiVE */
+       unsigned int cpuid:24;  /* 3 byte cpu id */
+       uint16_t model;         /* cpu model 2084,2094 etc. */
+       uint16_t flags;         /* 8000/0000 global unique id, et al */
+}__attribute__ ((packed));
+
+static struct cpu_id host_cpu_id;
+
+static int priv_store_cpu_id (struct zlcpu *cpu)
+{
+       uint64_t reg;
+       struct cpu_id *local;
+
+       reg = decode_base_displacement(cpu);
+       reg = apply_prefixing(cpu, reg);
+
+       check_addr(cpu, reg);
+       local = (struct cpu_id *) (reg+glo_origin);
+       local->version = 0xfe;
+       local->cpuid = host_cpu_id.cpuid;
+       local->model = host_cpu_id.model;
+       local->flags = 0;
+
+       return may_do_cpu_work(cpu);
+}
+
+/* Fills in skeleton for cpu id, cpu model etc
+ * - checks the config file for a cpuid entry
+ * - scans /proc/cpuinfo for a line which starts with processor */
+static void init_cpuid(void)
+{
+       FILE *cpuinfo;
+       char line[1024];
+       int num, version, cpuid, model;
+       int defined_cpuid;
+
+       defined_cpuid = strtol(get_configentry(glo_activesection,"cpuid"),
+                                                               NULL, 16);
+       if (defined_cpuid > 0xffffff) {
+               defined_cpuid &= 0xffffff;
+               screen("Invalid cpu identification specfied,"
+                       "truncated to %X", defined_cpuid & 0xffffff);
+       }
+       cpuinfo = fopen("/proc/cpuinfo", "r");
+       if (!cpuinfo)
+               report_it("Cannot read /proc/cpuinfo");
+       do {
+               fgets(line, 1024, cpuinfo);
+               if (memcmp(line,"processor ",10))
+                       continue;
+               sscanf(line,"processor %d: version = %d, identification = %X,  
machine = %X",
+                       &num, &version, &cpuid, &model);
+               host_cpu_id.version = version;
+               host_cpu_id.cpuid = cpuid;
+               host_cpu_id.model = model;
+               break;
+       } while (strlen(line));
+       if (defined_cpuid)
+               host_cpu_id.cpuid = defined_cpuid;
+}
+
+void priv_store_cpu_id_init(void)
+{
+       init_cpuid();
+       register_privileged_handler(PRIV_STORE_CPU_ID, priv_store_cpu_id);
+}
+
+__ZLAUTOINIT(priv_store_cpu_id_init)
Index: zlive/priv/store_facility_list.c
===================================================================
--- /dev/null
+++ zlive/priv/store_facility_list.c
@@ -0,0 +1,31 @@
+/*
+ * z/Live store facility list privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+
+static int priv_store_facility_list (struct zlcpu *cpu)
+{
+       struct lowcore *lowcore;
+
+       lowcore = (void *)(glo_origin + cl_get_prefix(cpu));
+
+       /* FIXME: this is very raw. simply return everything valid for T-Rex */
+       lowcore->stfl_fac_list = 0xfcf80000;
+       debug("store facility list at addr %lx", cl_get_psw(cpu).addr);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_store_facility_list_init(void)
+{
+       register_privileged_handler (PRIV_STORE_FACILITY_LIST, 
priv_store_facility_list);
+}
+
+__ZLAUTOINIT(priv_store_facility_list_init)
Index: zlive/priv/store_prefix.c
===================================================================
--- /dev/null
+++ zlive/priv/store_prefix.c
@@ -0,0 +1,32 @@
+/*
+ * z/Live store prefix privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *         Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+
+
+static int priv_store_prefix (struct zlcpu *cpu)
+{
+       uint64_t reg = decode_base_displacement(cpu);
+       reg = apply_prefixing(cpu, reg);
+       check_addr(cpu, reg);
+
+       *(uint32_t *)(unsigned long) (reg + glo_origin) = cl_get_prefix(cpu);
+       debug("store prefix at addr %lx", cl_get_psw(cpu).addr);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_store_prefix_init(void)
+{
+       register_privileged_handler (PRIV_STORE_PREFIX, priv_store_prefix);
+}
+
+__ZLAUTOINIT(priv_store_prefix_init)
Index: zlive/priv/store_subchannel.c
===================================================================
--- /dev/null
+++ zlive/priv/store_subchannel.c
@@ -0,0 +1,27 @@
+/*
+ * z/Live store subchannel privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Carsten Otte <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+
+static int priv_store_subchannel(struct zlcpu *cpu)
+{
+
+       debug("cpu %d: store subchannel at %lx", cpu->cpuno, 
cl_get_psw(cpu).addr);
+       setcc(cpu, 3);
+       return may_do_cpu_work(cpu);
+}
+
+void priv_store_subchannel_init(void)
+{
+       register_privileged_handler (PRIV_STORE_SUBCHANNEL, 
priv_store_subchannel);
+}
+
+__ZLAUTOINIT(priv_store_subchannel_init)
Index: zlive/priv/store_system_info.c
===================================================================
--- /dev/null
+++ zlive/priv/store_system_info.c
@@ -0,0 +1,284 @@
+/*
+ * z/Live store system information privileged instruction
+ * Copyright IBM Corp. 2007
+ * Author: Christian Borntraeger <[EMAIL PROTECTED]>
+ *
+ * This file is licensed under the terms of the GNU General Public License(GPL)
+ */
+
+#include <string.h>
+#include <zlautoinit.h>
+#include <zlpriv.h>
+#include <zlcpu.h>
+#include <zlcpu_lib.h>
+#include <system_info.h>
+
+
+/* returns the Function Code, which is bits 32-35 of GPRS 0*/
+static inline unsigned int FC(struct zlcpu *cpu)
+{
+       return (cpu->gpr->regs[0] >> 28) & 15;
+}
+
+
+/* returns Selector1, which is bits 56-63 of GPRS 0*/
+static inline unsigned int Selector1(struct zlcpu *cpu)
+{
+       return (cpu->gpr->regs[0] & 0xff);
+}
+
+/* returns Selector2, which is bits 48-63 of GPRS 0*/
+static inline unsigned int Selector2(struct zlcpu *cpu)
+{
+       return (cpu->gpr->regs[1] & 0xffff);
+}
+
+/* Basic machine configuration*/
+static int stsi_111(struct zlcpu *cpu)
+{
+       uint64_t address;
+       struct sysinfo_1_1_1 *stsi111;
+
+       address = decode_base_displacement(cpu);
+       address = apply_prefixing(cpu, address);
+       check_addr(cpu, address);
+       stsi111 = (struct sysinfo_1_1_1 *) address;
+       /*FIXME implement this using real values*/
+        memcpy(stsi111->manufacturer, "\xe3\xd6\xc4\xd6\x0", 5);
+        memcpy(stsi111->type, "\xe3\xd6\xc4\xd6\x0", 5);
+        memcpy(stsi111->model, "\xe3\xd6\xc4\xd6\x0", 5);
+        memcpy(stsi111->sequence, "\xe3\xd6\xc4\xd6\x0", 5);
+        memcpy(stsi111->plant, "\xe3\xd6\xc4\xd6\x0", 5);
+       setcc(cpu, 0);
+       cpu->gpr->regs[0] = 0;
+       return may_do_cpu_work(cpu);
+}
+
+
+/* Basic machine CPU*/
+static int stsi_121(struct zlcpu *cpu)
+{
+       /*FIXME: implement this */
+       setcc(cpu, 3);
+       return may_do_cpu_work(cpu);
+
+}
+
+/* Basic machine CPUs*/
+static int stsi_122(struct zlcpu *cpu)
+{
+       uint64_t address;
+       struct sysinfo_1_2_2 *stsi122;
+
+       address = decode_base_displacement(cpu);
+       address = apply_prefixing(cpu, address);
+       check_addr(cpu, address);
+       stsi122 = (struct sysinfo_1_2_2 *) address;
+       /*FIXME: implement this using real values*/
+       stsi122->capability = 0;
+       stsi122->cpus_total = 8;
+       stsi122->cpus_configured = 8;
+       stsi122->cpus_standby = 0;
+       stsi122->cpus_reserved = 0;
+       stsi122->cpus_total = 32;
+       setcc(cpu, 0);
+       return may_do_cpu_work(cpu);
+}
+
+/* Logical-partition CPU*/
+static int stsi_221(struct zlcpu *cpu)
+{
+       /*FIXME: implement this */
+       setcc(cpu, 3);
+       return may_do_cpu_work(cpu);
+}
+
+
+/* Logical-partition CPUs*/
+static int stsi_222(struct zlcpu *cpu)
+{
+       uint64_t address;
+       struct sysinfo_2_2_2 *stsi222;
+
+       address = decode_base_displacement(cpu);
+       address = apply_prefixing(cpu, address);
+       check_addr(cpu, address);
+       stsi222 = (struct sysinfo_2_2_2 *) address;
+       /*FIXME: implement this using real values*/
+       stsi222->lpar_number = 0;
+       stsi222->characteristics = 0;
+       stsi222->cpus_total = 8;
+       stsi222->cpus_configured = 8;
+       stsi222->cpus_standby = 0;
+       stsi222->cpus_reserved = 0;
+       memcpy(stsi222->name, "\xe3\xd6\xc4\xd6\x0", 5);
+       stsi222->caf = 100;
+       stsi222->cpus_dedicated = 0;
+       stsi222->cpus_shared = 8;
+
+
+       setcc(cpu, 0);
+       return may_do_cpu_work(cpu);
+}
+
+/* Virtual machine CPUs*/
+static int stsi_322(struct zlcpu *cpu)
+{
+       uint64_t address;
+       struct sysinfo_3_2_2 *stsi322;
+
+       address = decode_base_displacement(cpu);
+       address = apply_prefixing(cpu, address);
+       check_addr(cpu, address);
+       stsi322 = (struct sysinfo_3_2_2 *) address;
+       /*FIXME: implement this using real values*/
+       stsi322->count =1;
+       memcpy(stsi322->vm[0].cpi, "\xa9\x61\xd3\x89\xe5\xc5\x0", 7);
+       memcpy(stsi322->vm[0].name, "\xe3\xd6\xc4\xd6\x0", 5); //FIXME
+       stsi322->vm[0].cpus_total = glo_numcpu;
+       stsi322->vm[0].cpus_configured=glo_numcpu;
+       stsi322->vm[0].cpus_standby = 0;
+       stsi322->vm[0].cpus_reserved = 0;
+/*                unsigned int caf;
+                char reserved_1[24];
+
+ */
+
+       setcc(cpu, 0);
+       return may_do_cpu_work(cpu);
+}
+
+
+
+static int stsi_11(struct zlcpu *cpu)
+{
+       switch(Selector2(cpu)) {
+               case 1:
+                       return stsi_111(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+static int stsi_12(struct zlcpu *cpu)
+{
+       switch(Selector2(cpu)) {
+               case 1:
+                       return stsi_121(cpu);
+               case 2:
+                       return stsi_122(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+static int stsi_22(struct zlcpu *cpu)
+{
+       switch(Selector2(cpu)) {
+               case 1:
+                       return stsi_221(cpu);
+               case 2:
+                       return stsi_222(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+static int stsi_32(struct zlcpu *cpu)
+{
+       switch(Selector2(cpu)) {
+               case 2:
+                       return stsi_322(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+/* function code 0 of the stsi instruction requests the current
+ * configuration level number.  We state to be at level 3 */
+static int stsi_0(struct zlcpu *cpu)
+{
+       /*FIXME if zlive is running under VM we are level 4*/
+       cpu->gpr->regs[0] = 0x3 << 28;
+       setcc(cpu, 0);
+       return may_do_cpu_work(cpu);
+}
+
+
+/* function code 1 of the stsi instruction: basic machine info */
+static int stsi_1(struct zlcpu *cpu)
+{
+       switch(Selector1(cpu)) {
+               case 1:
+                       return stsi_11(cpu);
+               case 2:
+                       return stsi_12(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+/* function code 2 of the stsi instruction: LPAR */
+static int stsi_2(struct zlcpu *cpu)
+{
+       switch(Selector1(cpu)) {
+               case 2:
+                       return stsi_22(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+/* function code 3 of the stsi instruction: Virtual machine */
+static int stsi_3(struct zlcpu *cpu)
+{
+       switch(Selector1(cpu)) {
+               case 2:
+                       return stsi_32(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+static int invalid_regs(struct zlcpu *cpu)
+{
+       /* if the function is valid, bits 36-55 of reg0 and bits 32-47 of
+        * reg1 must be 0, otherwise send a specification exception*/
+       if (cpu->gpr->regs[0] & 0x000000000fffff00L)
+               return enter_pgmcheck(cpu, 0x0006);
+       if (cpu->gpr->regs[1] & 0x00000000ffff0000L)
+               return enter_pgmcheck(cpu, 0x0006);
+       return 0;
+}
+
+static int priv_store_system_info(struct zlcpu *cpu)
+{
+       /* decode instruction according to function code*/
+       switch(FC(cpu)) {
+               case 0:
+                       return invalid_regs(cpu) | stsi_0(cpu);
+               case 1:
+                       return invalid_regs(cpu) | stsi_1(cpu);
+               case 2:
+                       return invalid_regs(cpu) | stsi_2(cpu);
+               case 3:
+                       return invalid_regs(cpu) | stsi_3(cpu);
+               default:
+                       setcc(cpu, 3);
+                       return may_do_cpu_work(cpu);
+       }
+}
+
+void priv_store_system_info_init(void)
+{
+       register_privileged_handler (PRIV_STORE_SYSTEM_INFORMATION, 
priv_store_system_info);
+}
+
+__ZLAUTOINIT(priv_store_system_info_init)



-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to