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