public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* RFC: qemu acpi hotplug
@ 2008-01-16 21:12 Glauber de Oliveira Costa
       [not found] ` <478E7345.2050402-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 2+ messages in thread
From: Glauber de Oliveira Costa @ 2008-01-16 21:12 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Marcelo Tosatti,
	Chris Wright, Avi Kivity, aliguori-r/Jw6+rmf7HQT0dZR+AlfA

[-- Attachment #1: Type: text/plain, Size: 480 bytes --]

When it's more close to inclusion, I'd also post it to main qemu list. 
But right now, I'm just aiming at a first round around this draft.

The attached patch is enough to make the notifications DEVICE_CHECK and 
EJECT reach the kernel. As far as I understand, some userspace black 
magic that keeps changing its scroll is needed to really put the 
processors logically off/on after the notify (acpi code itself will 
never call cpu_up/down)

Just let me tell you what you think.

[-- Attachment #2: 0001-RFC-qemu-cpu-hotplug.patch --]
[-- Type: text/x-patch, Size: 11221 bytes --]

>From c45432c0cec8241dbcd6ed6cf38c953b17a6f826 Mon Sep 17 00:00:00 2001
From: Glauber de Oliveira Costa <gcosta-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Date: Wed, 16 Jan 2008 18:43:11 -0200
Subject: [PATCH] RFC: qemu cpu hotplug

Signed-off-by: Glauber de Oliveira Costa <gcosta-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 bios/acpi-dsdt.dsl    |   87 +++++++++++++++++++++++++++++-----
 bios/rombios32.c      |    2 +
 qemu/hw/acpi.c        |  125 +++++++++++++++++++++++++++++++++++++++++++++++++
 qemu/hw/pc.c          |    4 +-
 qemu/monitor.c        |    9 ++++
 qemu/pc-bios/bios.bin |  Bin
 6 files changed, 214 insertions(+), 13 deletions(-)

diff --git a/bios/acpi-dsdt.dsl b/bios/acpi-dsdt.dsl
index df255ce..497b866 100755
--- a/bios/acpi-dsdt.dsl
+++ b/bios/acpi-dsdt.dsl
@@ -27,18 +27,35 @@ DefinitionBlock (
 {
     Scope (_PR)
     {
-        Processor (CPU0, 0x00, 0x0000b010, 0x06) {}
-        Processor (CPU1, 0x01, 0x0000b010, 0x06) {}
-        Processor (CPU2, 0x02, 0x0000b010, 0x06) {}
-        Processor (CPU3, 0x03, 0x0000b010, 0x06) {}
-        Processor (CPU4, 0x04, 0x0000b010, 0x06) {}
-        Processor (CPU5, 0x05, 0x0000b010, 0x06) {}
-        Processor (CPU6, 0x06, 0x0000b010, 0x06) {}
-        Processor (CPU7, 0x07, 0x0000b010, 0x06) {}
-        Processor (CPU8, 0x08, 0x0000b010, 0x06) {}
-        Processor (CPU9, 0x09, 0x0000b010, 0x06) {}
-        Processor (CPUA, 0x0a, 0x0000b010, 0x06) {}
-        Processor (CPUB, 0x0b, 0x0000b010, 0x06) {}
+	OperationRegion( PRO, SystemIO, 0xaf00, 0x02)
+	Field (PRO, ByteAcc, NoLock, WriteAsZeros)
+	{
+		PR0U, 1,
+		PR1U, 1,
+		PR2U, 1,
+		PR3U, 1,
+		PR4U, 1,
+		PADU, 3,
+
+		PR0D, 1,
+		PR1D, 1,
+		PR2D, 1,
+		PR3D, 1,
+		PR4D, 1,
+		PADD, 3,
+	}
+        Processor (CPU0, 0x00, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU1, 0x01, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU2, 0x02, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU3, 0x03, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU4, 0x04, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} } 
+        Processor (CPU5, 0x05, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU6, 0x06, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU7, 0x07, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU8, 0x08, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPU9, 0x09, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPUA, 0x0a, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
+        Processor (CPUB, 0x0b, 0x0000b010, 0x06) { Method (_STA) { Return(0x1)} }
         Processor (CPUC, 0x0c, 0x0000b010, 0x06) {}
         Processor (CPUD, 0x0d, 0x0000b010, 0x06) {}
         Processor (CPUE, 0x0e, 0x0000b010, 0x06) {}
@@ -559,6 +576,51 @@ DefinitionBlock (
                 }
         }
     }
+    Scope(\_GPE)
+    {
+       Method(_L00) {  
+	  Return(0x01)
+       }
+       Method(_L01) { 
+         If (\_PR.PR1U) {
+	  Notify(\_PR.CPU1, 1)
+	 }
+	 If (\_PR.PR1D){
+	  Notify(\_PR.CPU1, 3) 
+	 }
+	 Return(0x01)
+       }
+
+       Method(_L02) { 
+         If (\_PR.PR2U) {
+	  Notify(\_PR.CPU2, 1)
+	 }
+	 If (\_PR.PR2D){
+	  Notify(\_PR.CPU2, 3) 
+	 }
+	 Return(0x01)
+       }
+
+       Method(_L03) { 
+         If (\_PR.PR3U) {
+	  Notify(\_PR.CPU3, 1)
+	 }
+	 If (\_PR.PR3D){
+	  Notify(\_PR.CPU3, 3) 
+	 }
+	 Return(0x01)
+       }
+
+       Method(_L04) { 
+         If (\_PR.PR4U) {
+	  Notify(\_PR.CPU4, 1)
+	 }
+	 IF (\_PR.PR4D) {
+	  Notify(\_PR.CPU4, 3) 
+	 }
+	 Return(0x01)
+       }
+    }
 
     /* S5 = power off state */
     Name (_S5, Package (4) {
@@ -567,4 +629,5 @@ DefinitionBlock (
         0x00, // reserved
         0x00, // reserved
     })
+
 }
diff --git a/bios/rombios32.c b/bios/rombios32.c
index 967c119..4580462 100755
--- a/bios/rombios32.c
+++ b/bios/rombios32.c
@@ -1329,6 +1329,8 @@ void acpi_bios_init(void)
     fadt->pm_tmr_len = 4;
     fadt->plvl2_lat = cpu_to_le16(0x0fff); // C2 state not supported
     fadt->plvl3_lat = cpu_to_le16(0x0fff); // C3 state not supported
+    fadt->gpe0_blk = cpu_to_le32(0xafe0);
+    fadt->gpe0_blk_len = 4;
     /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
     fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
     acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", 
diff --git a/qemu/hw/acpi.c b/qemu/hw/acpi.c
index b97b37d..6e1af9e 100644
--- a/qemu/hw/acpi.c
+++ b/qemu/hw/acpi.c
@@ -530,3 +530,128 @@ void qemu_system_powerdown(void)
     }
 }
 #endif
+
+struct gpe_things {
+	uint16_t sts;	
+	uint16_t en;	
+	uint8_t pru;
+	uint8_t prd;
+};
+
+static struct gpe_things gpe;
+unsigned long gpe_base = 0xafe0;
+
+static uint32_t gpe_readb(void *opaque, uint32_t addr)
+{
+	struct gpe_things *g = opaque;
+	uint32_t val;
+
+	switch (addr) {
+		case 0xaf00:
+			val =  g->pru;		
+			break;
+		case 0xaf01:
+			val =  g->prd;		
+			break;
+		case 0xafe0:
+			val =  g->sts & 0xFF;
+			break;
+		case 0xafe1:
+			val =  (g->sts >> 8) & 0xFF;
+			break;
+		case 0xafe0 + 2:
+			val =  g->en & 0xFF;
+			break;
+		case 0xafe3:
+			val =  (g->en >> 8) & 0xFF;
+			break;
+		default:
+			break;
+	}
+	printf("gpe read %lx == %lx\n", addr, val);
+	return val;
+
+}
+
+static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+	struct gpe_things *g = opaque;
+
+	switch (addr) {
+		case 0xaf00:
+			break;
+		case 0xafe0:
+			g->sts = (g->sts & ~0xFFFF) | (val & 0xFFFF);
+			break;
+		case 0xafe1:
+			g->sts = (g->sts & 0xFFFF) | (val << 8);
+			break;
+		case 0xafe0 + 2:
+			g->en =  (g->en & ~0xFFFF) | (val & 0xFFFF);
+			break;
+		case 0xafe3:
+			g->en =  (g->en & 0xFFFF) | (val << 8);
+			break;
+
+		default:
+			break;
+	}
+
+	printf("gpe write %lx <== %d\n", addr, val);
+}
+
+int current_cpus = 0;
+void qemu_system_hot_add_init(void)
+{
+	int i;
+	for (i = 0; i < smp_cpus; i++)
+		gpe.pru |= (1 << i);
+
+	current_cpus = smp_cpus;
+
+	register_ioport_write(gpe_base, 4, 1, gpe_writeb, &gpe);
+	register_ioport_read(gpe_base, 4, 1,  gpe_readb, &gpe);
+
+	register_ioport_write(0xaf00, 4, 1, gpe_writeb, &gpe);
+	register_ioport_read(0xaf00, 4, 1,  gpe_readb, &gpe);
+}
+
+static void enable_processor(struct gpe_things *g, int cpu)
+{
+	g->sts |= (1 << cpu);
+	g->en |= (1 << cpu);
+	g->pru |= (1 << cpu);
+	g->prd &= ~(1 << cpu);
+}
+
+static void disable_processor(struct gpe_things *g, int cpu)
+{
+	g->sts |= (1 << cpu);
+	g->en |= (1 << cpu);
+	g->pru &= ~(1 << cpu);
+	g->prd |= (1 << cpu);
+}
+
+void qemu_system_cpu_hot_add(int cpus)
+{
+    int i;
+
+    gpe.sts = 0;
+    gpe.en = 0;
+    gpe.pru = 0;
+    gpe.prd = 0;
+
+    qemu_set_irq(pm_state->dev.irq[0], 1);
+
+    for (i = current_cpus ; i < cpus; i++) {
+	enable_processor(&gpe, i);
+	printf("proc %i up (%d %d)\n", i, gpe.sts, gpe.en);
+    }	
+    for (i = current_cpus - 1 ; i >= cpus; i--) {
+	disable_processor(&gpe, i);
+	printf("proc %i down (%d %d)\n", i, gpe.sts, gpe.en);
+    }	
+
+    qemu_set_irq(pm_state->dev.irq[0], 0);
+
+}
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 3972ab4..5ce28ab 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -1029,7 +1029,9 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
         }
     }
 
-#define USE_HYPERCALL
+    qemu_system_hot_add_init();
+
+#undef USE_HYPERCALL
 #ifdef USE_HYPERCALL
     pci_hypercall_init(pci_bus);
 #endif
diff --git a/qemu/monitor.c b/qemu/monitor.c
index e03c473..effb696 100644
--- a/qemu/monitor.c
+++ b/qemu/monitor.c
@@ -346,6 +346,14 @@ static void do_cpu_set(int index)
         term_printf("Invalid CPU index\n");
 }
 
+static void do_cpu_set_nr(int value)
+{
+    if ((value < 1) || (value > 32)) /* second condition is possibly bogus. OS dependant */
+       term_printf("value out of range\n");
+    qemu_system_cpu_hot_add(value);
+
+}
+
 static void do_info_jit(void)
 {
     dump_exec_info(NULL, monitor_fprintf);
@@ -1339,6 +1347,7 @@ static term_cmd_t term_cmds[] = {
       "", "cancel the current VM migration" },
     { "migrate_set_speed", "s", do_migrate_set_speed,
       "value", "set maximum speed (in bytes) for migrations" },
+    { "cpu_set", "i", do_cpu_set_nr, "value", "number of cpus in the guest" },
     { NULL, NULL, },
 };
 
diff --git a/qemu/pc-bios/bios.bin b/qemu/pc-bios/bios.bin
index 7462753c0462e6fc863c0669664d363788e08ff3..7599b8d8956141d3355616c12bad85ac3ee112ae 100644
GIT binary patch
delta 1683
zc${riZ%i9y7=PdE6^^4w)eh>Wp>EBB0Z0EFShO>=S4K7lltS57aK-2@(Tm1KFZ&?U
zVuy0+5R!}G(-H_KEShZ7E<;${TAV!$ewgut7{1iS#9Ls>qOz!k^L-1#IeQ<T_j!K5
z=l9%m&vSRtC>4!Tv^{xa{Z$goxcN`%ptrK|o97yn{knK#QcPC~HwV}Ht)*96E{m)2
z;H}Z&xAub}IyMJmO5%O5nV=r$Ng$R~^NA^6l&G|zNY(>nK@uR3#2x^v2US%anWRv3
zhL-gdpJ;2!K(h_Sin5`qVtTm2D&C*Oz=VaDnhsm3O5_jBH55y49==&-LP45k?xoq<
zRq<^rC$a}7T)fnB<gthgQL!W`vJDfiT-I?i&7L6AY&RK8QX+d)T$EXV<`O_u4=J;6
zoI(vLx7JnFo}4ivKl|G!@!*O~9P+RovX^W?knFQk>vZlUK`#m7Evurzs&xOMs_}P}
z9EvWn&q~Fs8Z#nkRUXDvFcUAqZOdLO0GSQhTM1EGY_59n>;4*ha#SLl_txQr$l`Ek
zsya=;8Juv<@(^my3k?&SVmv$~rtm$6yhLoyuuMt4&4Gf?vZ~6BCX&tPVFjLX?Dneo
z-TkEtP%sVrjV7$So||ytb&{9*T7DqVgpRdV6J}l-Y<-q6@lvWaOc;1+Z(Ci70nff-
zO;u$*!zWI)>7eNe1QD_xH-Xy{Do{UCpZ@~_9ftN+0xhPe{fH4SX)sxOmerwWJBYZe
z?G=QLm%eZB!kIOJT6}PU2tIxeoWw^{NBYs+w&~whb#~-9dS|{w+m<Yy=dko*XZbz`
zmt7KUrA4zR(A_`JHTdp5l#W9&g@A<8Sq95-9T6=EuVLjF35HFSxXa2*ySh#nV$r0L
zPYidRDJsAlgewx=yC-tU9QFso-BEv_EewmnC7S3SU`ZT#`~h1K`U7@s9N0LqVUY3o
zf;z<dFpG@?8z(l553@d9cg)24gEnBi3_yX23U_pRz(;TswZk1WvI9Gae92B-K9nKz
zp|$#aXk9@*^qImO`r-qyi^`W=Uz88^(D_hr@qf{T+$&HKV^e9k$=`_3qc$5tP4&pJ
zgYoj719<*;%I|HuxdDxvw{f2ar*&IOheqkpC><K5L!*p1wxv#u)Txm=HBzTW>fBZ`
z8YQDqG8!eLQ8HMG#!wr6B;kFf=))`Ur71f0vX#o7UqCPJ*lSa8Pn89IP;NqSrG7MW
z;<ucAiMxS*LS+c$X0wL7_47gr7ux`W{?6K1VhTQK&VVf{rBE97i?Nj{xI1zYu>nr}
zi;LaXaRYN%!%Ao<b>|#H-9^G~Wn_mYax`~0#EGfp*WI*WR8HquTswrYkh@qgD=$1)
zaA^LQ(DL(c1FGivUp1RJ&;1%&wzx}BxqbhZ6Xy|TxH1qvx%u>eF4%tB@~5v|fL}p9
j{-J^C$j5NuX;?qqya=D#55v>K20RN3>uYQ-kRAUA;utKq

delta 1195
zc${UDT}%{L6vywKorT$D*WE-Eszy{MijgX`@}aJY?qCp>kKOGq;!1^9nK1oGFgjx5
z3bP$Zx!G<pnHZjUAUv$;Lt`^26^+hPyGv^yYD`)hUZ`o>v0w{LtFa|a@7-3NwDWTA
z@BHum-*e9yNn#|4v6pMN4+}K7-Y<M&4|_|(U+oKPy_R@bL*MKW?+iTdWnI?}T|vLa
z8^6AoII|TDLOBKHpVjxhg%ooVpG3|xf|{(6sFE&B87pxE8o;XtvI1anzhM|dV}49M
z_KejpsLi!=u<#saU0*Q_lujIA(UUQf80`|2+B%l$#_QPBpiMblcV}%IhBUW(Da}<Z
zqVp_|xSgYtpfuLMR4QRf)@Z~X7?rZSTIn=*luC2QXjx+r*MMd+Tz4m~LZ4Me>Nf`t
z+i+zyEDbtn5N}*W4p!&?FpT&GJ)6ZJin2`n&>W&!eFIU#b8#mrC*x%Sm|MwsOCa7Q
zPn8aQ(Yv!;Q{28S8;RaGlL)0s(-gc;^c$O20g(1W$7r{p_<aRd2Wg(t<qNKwTsDlv
zS&+E7ja;W{z7beNnkGM3ME9S}UWQ_R>@VCh%dKq7a&I*VO0@Ai3P1TsQz_LUC<9G<
zsWw4LHMLVALD|w==?sx(7CknMj5R8#oy``Q--%OH#!5;f1&KwZlBoYf3I|7^iNc+3
z3)H(w*9SCLKWD*@+K;tsfg<XhpnMx>Av<>kD@fpjeI)!8JWfLGYw6Y5@!5YjjLD%^
z{1beJ$ER!xeL#+W94aV|65Cm^%w?NAif{ikTi|<3csoIq!U<Imt%U`|2i33)Y5&3z
z8YJ==wB{W_S<`YVmmC^v71Tsak1dBx4r+?MV|`zpqun2DKPKmK{%{#^UjZQJA1H?=
zc!e^-s}>XNrcF>`H9=*L3952UP|ZAtVt;s#%_JSPo4}iw1-1VTkx`f4a$Qp0Z(oJu
z@I=xcJIOM5_QuHF;dhg8{f=Th7Y`*?r@nXd=pJ7_%iqTT=?0wTCzl<M_DqXTUS0vB
z_2JWDH3>Ht{s{h+QaWQ&wc&*%T-P^_)gX`l<mCqzJ~p-NScnX!9uDEG$0n}RFTIed
ztjs@(@F+EZ%3~MZdQVm*-VvO8-IFI4>L>ndI5_=FWd5MXf!%8V=T?cP`ClXR#U3ZN
z+y2ZBP2-$vJl1~v`RkwFE&JgGPF%eVKZg_2NASy+Vbz3h25#R9J14{y*bj57c9m6w
H<v0HZp>4X&

-- 
1.5.0.6


[-- Attachment #3: Type: text/plain, Size: 228 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

[-- Attachment #4: Type: text/plain, Size: 186 bytes --]

_______________________________________________
kvm-devel mailing list
kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
https://lists.sourceforge.net/lists/listinfo/kvm-devel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: RFC: qemu acpi hotplug
       [not found] ` <478E7345.2050402-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2008-01-19  8:14   ` Avi Kivity
  0 siblings, 0 replies; 2+ messages in thread
From: Avi Kivity @ 2008-01-19  8:14 UTC (permalink / raw)
  To: Glauber de Oliveira Costa
  Cc: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, Marcelo Tosatti

Glauber de Oliveira Costa wrote:
> When it's more close to inclusion, I'd also post it to main qemu list. 
> But right now, I'm just aiming at a first round around this draft.
>
> The attached patch is enough to make the notifications DEVICE_CHECK 
> and EJECT reach the kernel. As far as I understand, some userspace 
> black magic that keeps changing its scroll is needed to really put the 
> processors logically off/on after the notify (acpi code itself will 
> never call cpu_up/down)
>
> Just let me tell you what you think.

You aren't the only hypervisor developer to encounter this:

  
http://www.gossamer-threads.com/lists/linux/kernel/866461?do=post_view_threaded


The patch looks good.  One thing we might change is to use just one gpe 
as a "something processor related has changed" and look up some other 
pio word to see exactly what, that may be simpler with larger numbers of 
processors (maybe).

-- 
Any sufficiently difficult bug is indistinguishable from a feature.


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-01-19  8:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-16 21:12 RFC: qemu acpi hotplug Glauber de Oliveira Costa
     [not found] ` <478E7345.2050402-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2008-01-19  8:14   ` Avi Kivity

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox