Commit ca602818 authored by Peter Maydell's avatar Peter Maydell

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pc, pci, misc bugfixes

A bunch of bugfixes for 2.2.
Signed-off-by: 's avatarMichael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon 24 Nov 2014 18:59:47 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  pc: acpi: mark all possible CPUs as enabled in SRAT
  pcie: fix improper use of negative value
  pcie: fix typo in pcie_cap_deverr_init()
  target-i386: move generic memory hotplug methods to DSDTs
  acpi-build: mark RAM dirty on table update
  hw/pci: fix crash on shpc error flow
  pc: count in 1Gb hugepage alignment when sizing hotplug-memory container
  pc: explicitly check maxmem limit when adding DIMM
  pc: pc-dimm: use backend alignment during address auto allocation
  pc: align DIMM's address/size by backend's alignment value
  memory: expose alignment used for allocating RAM as MemoryRegion API
  pc: limit DIMM address and size to page aligned values
  pc: make pc_dimm_plug() more readble
  pc: kvm: check if KVM has free memory slots to avoid abort()
  qemu-char: fix tcp_get_fds
Signed-off-by: 's avatarPeter Maydell <peter.maydell@linaro.org>
parents 3d4a70f8 dd0247e0
...@@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, ...@@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
uint16_t section); uint16_t section);
static subpage_t *subpage_init(AddressSpace *as, hwaddr base); static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc; static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
qemu_anon_ram_alloc;
/* /*
* Set a custom physical guest memory alloator. * Set a custom physical guest memory alloator.
* Accelerators with unusual needs may need this. Hopefully, we can * Accelerators with unusual needs may need this. Hopefully, we can
* get rid of it eventually. * get rid of it eventually.
*/ */
void phys_mem_set_alloc(void *(*alloc)(size_t)) void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align))
{ {
phys_mem_alloc = alloc; phys_mem_alloc = alloc;
} }
...@@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block, ...@@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block,
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto error; goto error;
} }
block->mr->align = hpagesize;
if (memory < hpagesize) { if (memory < hpagesize) {
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to " error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
...@@ -1309,7 +1311,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) ...@@ -1309,7 +1311,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
if (xen_enabled()) { if (xen_enabled()) {
xen_ram_alloc(new_block->offset, new_block->length, new_block->mr); xen_ram_alloc(new_block->offset, new_block->length, new_block->mr);
} else { } else {
new_block->host = phys_mem_alloc(new_block->length); new_block->host = phys_mem_alloc(new_block->length,
&new_block->mr->align);
if (!new_block->host) { if (!new_block->host) {
error_setg_errno(errp, errno, error_setg_errno(errp, errno,
"cannot set up guest memory '%s'", "cannot set up guest memory '%s'",
......
...@@ -811,12 +811,12 @@ err: ...@@ -811,12 +811,12 @@ err:
return -1; return -1;
} }
void *rom_add_blob(const char *name, const void *blob, size_t len, ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name, hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque) FWCfgReadCallback fw_callback, void *callback_opaque)
{ {
Rom *rom; Rom *rom;
void *data = NULL; ram_addr_t ret = RAM_ADDR_MAX;
rom = g_malloc0(sizeof(*rom)); rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name); rom->name = g_strdup(name);
...@@ -828,11 +828,13 @@ void *rom_add_blob(const char *name, const void *blob, size_t len, ...@@ -828,11 +828,13 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
rom_insert(rom); rom_insert(rom);
if (fw_file_name && fw_cfg) { if (fw_file_name && fw_cfg) {
char devpath[100]; char devpath[100];
void *data;
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
if (rom_file_has_mr) { if (rom_file_has_mr) {
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
ret = memory_region_get_ram_addr(rom->mr);
} else { } else {
data = rom->data; data = rom->data;
} }
...@@ -841,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len, ...@@ -841,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
fw_callback, callback_opaque, fw_callback, callback_opaque,
data, rom->romsize); data, rom->romsize);
} }
return data; return ret;
} }
/* This function is specific for elf program because we don't need to allocate /* This function is specific for elf program because we don't need to allocate
......
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
#include "qapi/qmp/qint.h" #include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h" #include "qom/qom-qobject.h"
#include "exec/ram_addr.h"
/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
* -M pc-i440fx-2.0. Even if the actual amount of AML generated grows * -M pc-i440fx-2.0. Even if the actual amount of AML generated grows
...@@ -1269,8 +1270,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, ...@@ -1269,8 +1270,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
} }
static void static void
build_srat(GArray *table_data, GArray *linker, build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
{ {
AcpiSystemResourceAffinityTable *srat; AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorAffinity *core; AcpiSratProcessorAffinity *core;
...@@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker, ...@@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker,
core->proximity_lo = curnode; core->proximity_lo = curnode;
memset(core->proximity_hi, 0, 3); memset(core->proximity_hi, 0, 3);
core->local_sapic_eid = 0; core->local_sapic_eid = 0;
if (test_bit(i, cpu->found_cpus)) { core->flags = cpu_to_le32(1);
core->flags = cpu_to_le32(1);
} else {
core->flags = cpu_to_le32(0);
}
} }
...@@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) ...@@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
typedef typedef
struct AcpiBuildState { struct AcpiBuildState {
/* Copy of table in RAM (for patching). */ /* Copy of table in RAM (for patching). */
uint8_t *table_ram; ram_addr_t table_ram;
uint32_t table_size; uint32_t table_size;
/* Is table patched? */ /* Is table patched? */
uint8_t patched; uint8_t patched;
...@@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables) ...@@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
} }
if (guest_info->numa_nodes) { if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables->table_data); acpi_add_table(table_offsets, tables->table_data);
build_srat(tables->table_data, tables->linker, &cpu, guest_info); build_srat(tables->table_data, tables->linker, guest_info);
} }
if (acpi_get_mcfg(&mcfg)) { if (acpi_get_mcfg(&mcfg)) {
acpi_add_table(table_offsets, tables->table_data); acpi_add_table(table_offsets, tables->table_data);
...@@ -1716,9 +1712,12 @@ static void acpi_build_update(void *build_opaque, uint32_t offset) ...@@ -1716,9 +1712,12 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
acpi_build(build_state->guest_info, &tables); acpi_build(build_state->guest_info, &tables);
assert(acpi_data_len(tables.table_data) == build_state->table_size); assert(acpi_data_len(tables.table_data) == build_state->table_size);
memcpy(build_state->table_ram, tables.table_data->data, memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
build_state->table_size); build_state->table_size);
cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
build_state->table_size);
acpi_build_tables_cleanup(&tables, true); acpi_build_tables_cleanup(&tables, true);
} }
...@@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque) ...@@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque)
build_state->patched = 0; build_state->patched = 0;
} }
static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob, static ram_addr_t acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
const char *name) const char *name)
{ {
return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name, return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
...@@ -1777,6 +1776,7 @@ void acpi_setup(PcGuestInfo *guest_info) ...@@ -1777,6 +1776,7 @@ void acpi_setup(PcGuestInfo *guest_info)
/* Now expose it all to Guest */ /* Now expose it all to Guest */
build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data, build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE); ACPI_BUILD_TABLE_FILE);
assert(build_state->table_ram != RAM_ADDR_MAX);
build_state->table_size = acpi_data_len(tables.table_data); build_state->table_size = acpi_data_len(tables.table_data);
acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader"); acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
......
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that 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 <http://www.gnu.org/licenses/>.
*/
External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
Scope(\_SB.PCI0) {
Device(MEMORY_HOTPLUG_DEVICE) {
Name(_HID, "PNP0A06")
Name(_UID, "Memory hotplug resources")
External(MEMORY_SLOTS_NUMBER, IntObj)
/* Memory hotplug IO registers */
OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
ACPI_MEMORY_HOTPLUG_BASE,
ACPI_MEMORY_HOTPLUG_IO_LEN)
Name(_CRS, ResourceTemplate() {
IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
})
Method(_STA, 0) {
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
Return(0x0)
}
/* present, functioning, decoding, not shown in UI */
Return(0xB)
}
Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
MEMORY_SLOT_ADDR_LOW, 32, // read only
MEMORY_SLOT_ADDR_HIGH, 32, // read only
MEMORY_SLOT_SIZE_LOW, 32, // read only
MEMORY_SLOT_SIZE_HIGH, 32, // read only
MEMORY_SLOT_PROXIMITY, 32, // read only
}
Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
Offset(20),
MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only
MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
}
Mutex (MEMORY_SLOT_LOCK, 0)
Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only
MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only
MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only
}
Method(MEMORY_SLOT_SCAN_METHOD, 0) {
If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
Return(Zero)
}
Store(Zero, Local0) // Mem devs iterrator
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
Store(1, MEMORY_SLOT_INSERT_EVENT)
}
// TODO: handle memory eject request
Add(Local0, One, Local0) // goto next DIMM
}
Release(MEMORY_SLOT_LOCK)
Return(One)
}
Method(MEMORY_SLOT_STATUS_METHOD, 1) {
Store(Zero, Local0)
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
If (LEqual(MEMORY_SLOT_ENABLED, One)) {
Store(0xF, Local0)
}
Release(MEMORY_SLOT_LOCK)
Return(Local0)
}
Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Name(MR64, ResourceTemplate() {
QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x0000000000000000, // Address Space Granularity
0x0000000000000000, // Address Range Minimum
0xFFFFFFFFFFFFFFFE, // Address Range Maximum
0x0000000000000000, // Address Translation Offset
0xFFFFFFFFFFFFFFFF, // Address Length
,, MW64, AddressRangeMemory, TypeStatic)
})
CreateDWordField(MR64, 14, MINL)
CreateDWordField(MR64, 18, MINH)
CreateDWordField(MR64, 38, LENL)
CreateDWordField(MR64, 42, LENH)
CreateDWordField(MR64, 22, MAXL)
CreateDWordField(MR64, 26, MAXH)
Store(MEMORY_SLOT_ADDR_HIGH, MINH)
Store(MEMORY_SLOT_ADDR_LOW, MINL)
Store(MEMORY_SLOT_SIZE_HIGH, LENH)
Store(MEMORY_SLOT_SIZE_LOW, LENL)
// 64-bit math: MAX = MIN + LEN - 1
Add(MINL, LENL, MAXL)
Add(MINH, LENH, MAXH)
If (LLess(MAXL, MINL)) {
Add(MAXH, One, MAXH)
}
If (LLess(MAXL, One)) {
Subtract(MAXH, One, MAXH)
}
Subtract(MAXL, One, MAXL)
If (LEqual(MAXH, Zero)){
Name(MR32, ResourceTemplate() {
DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0xFFFFFFFE, // Address Range Maximum
0x00000000, // Address Translation Offset
0xFFFFFFFF, // Address Length
,, MW32, AddressRangeMemory, TypeStatic)
})
CreateDWordField(MR32, MW32._MIN, MIN)
CreateDWordField(MR32, MW32._MAX, MAX)
CreateDWordField(MR32, MW32._LEN, LEN)
Store(MINL, MIN)
Store(MAXL, MAX)
Store(LENL, LEN)
Release(MEMORY_SLOT_LOCK)
Return(MR32)
}
Release(MEMORY_SLOT_LOCK)
Return(MR64)
}
Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Store(MEMORY_SLOT_PROXIMITY, Local0)
Release(MEMORY_SLOT_LOCK)
Return(Local0)
}
Method(MEMORY_SLOT_OST_METHOD, 4) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Store(Arg1, MEMORY_SLOT_OST_EVENT)
Store(Arg2, MEMORY_SLOT_OST_STATUS)
Release(MEMORY_SLOT_LOCK)
}
} // Device()
} // Scope()
...@@ -297,13 +297,12 @@ DefinitionBlock ( ...@@ -297,13 +297,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h" #include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE #define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl" #include "acpi-dsdt-cpu-hotplug.dsl"
#include "acpi-dsdt-mem-hotplug.dsl"
/**************************************************************** /****************************************************************
* General purpose events * General purpose events
****************************************************************/ ****************************************************************/
External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
Scope(\_GPE) { Scope(\_GPE) {
Name(_HID, "ACPI0006") Name(_HID, "ACPI0006")
......
...@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = { ...@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x53, 0x53,
0x44, 0x44,
0x54, 0x54,
0xf7, 0x8,
0xa, 0xe,
0x0, 0x0,
0x0, 0x0,
0x1, 0x1,
0x1f, 0xfc,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
...@@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = { ...@@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x54, 0x54,
0x4c, 0x4c,
0x28, 0x28,
0x5, 0x8,
0x10, 0x14,
0x20, 0x20,
0x10, 0x10,
0x49, 0x49,
...@@ -2593,6 +2593,791 @@ static unsigned char AcpiDsdtAmlCode[] = { ...@@ -2593,6 +2593,791 @@ static unsigned char AcpiDsdtAmlCode[] = {
0xa, 0xa,
0xb, 0xb,
0x10, 0x10,
0x40,
0x31,
0x2e,
0x5f,
0x53,
0x42,
0x5f,
0x50,
0x43,
0x49,
0x30,
0x5b,
0x82,
0x43,
0x30,
0x4d,
0x48,
0x50,
0x44,
0x8,
0x5f,
0x48,
0x49,
0x44,
0xd,
0x50,
0x4e,
0x50,
0x30,
0x41,
0x30,
0x36,
0x0,
0x8,
0x5f,
0x55,
0x49,
0x44,
0xd,
0x4d,
0x65,
0x6d,
0x6f,
0x72,
0x79,
0x20,
0x68,
0x6f,
0x74,
0x70,
0x6c,
0x75,
0x67,
0x20,
0x72,
0x65,
0x73,
0x6f,
0x75,
0x72,
0x63,
0x65,
0x73,
0x0,
0x5b,
0x80,
0x48,
0x50,
0x4d,
0x52,
0x1,
0xb,
0x0,
0xa,
0xa,
0x18,
0x8,
0x5f,
0x43,
0x52,
0x53,
0x11,
0xd,
0xa,
0xa,
0x47,
0x1,
0x0,
0xa,
0x0,
0xa,
0x0,
0x18,
0x79,
0x0,
0x14,
0x13,
0x5f,
0x53,
0x54,
0x41,
0x0,
0xa0,
0x9,
0x93,
0x4d,
0x44,
0x4e,
0x52,
0x0,
0xa4,
0x0,
0xa4,
0xa,
0xb,
0x5b,
0x81,
0x1f,
0x48,
0x50,
0x4d,
0x52,
0x3,
0x4d,
0x52,
0x42,
0x4c,
0x20,
0x4d,
0x52,
0x42,
0x48,
0x20,
0x4d,
0x52,
0x4c,
0x4c,
0x20,
0x4d,
0x52,
0x4c,
0x48,
0x20,
0x4d,
0x50,
0x58,
0x5f,
0x20,
0x5b,
0x81,
0x13,
0x48,
0x50,
0x4d,
0x52,
0x1,
0x0,
0x40,
0xa,
0x4d,
0x45,
0x53,
0x5f,
0x1,
0x4d,
0x49,
0x4e,
0x53,
0x1,
0x5b,
0x1,
0x4d,
0x4c,
0x43,
0x4b,
0x0,
0x5b,
0x81,
0x15,
0x48,
0x50,
0x4d,
0x52,
0x3,
0x4d,
0x53,
0x45,
0x4c,
0x20,
0x4d,
0x4f,
0x45,
0x56,
0x20,
0x4d,
0x4f,
0x53,
0x43,
0x20,
0x14,
0x4a,
0x4,
0x4d,
0x53,
0x43,
0x4e,
0x0,
0xa0,
0x9,
0x93,
0x4d,
0x44,
0x4e,
0x52,
0x0,
0xa4,
0x0,
0x70,
0x0,
0x60,
0x5b,
0x23,
0x4d,
0x4c,
0x43,
0x4b,
0xff,
0xff,
0xa2,
0x25,
0x95,
0x60,
0x4d,
0x44,
0x4e,
0x52,
0x70,
0x60,
0x4d,
0x53,
0x45,
0x4c,
0xa0,
0x13,
0x93,
0x4d,
0x49,
0x4e,
0x53,
0x1,
0x4d,
0x54,
0x46,
0x59,
0x60,
0x1,
0x70,
0x1,
0x4d,
0x49,
0x4e,
0x53,
0x72,
0x60,
0x1,
0x60,
0x5b,
0x27,
0x4d,
0x4c,
0x43,
0x4b,
0xa4,
0x1,
0x14,
0x2d,
0x4d,
0x52,
0x53,
0x54,
0x1,
0x70,
0x0,
0x60,
0x5b,
0x23,
0x4d,
0x4c,